Initial commit. Not in build system so shouldn't interfere with anything at this...
authorRobert Holcomb <bob_holcomb@hotmail.com>
Sat, 24 Mar 2007 06:57:29 +0000 (06:57 +0000)
committerRobert Holcomb <bob_holcomb@hotmail.com>
Sat, 24 Mar 2007 06:57:29 +0000 (06:57 +0000)
60 files changed:
source/blender/nodes/CMP_node.h [new file with mode: 0644]
source/blender/nodes/SHD_node.h [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_blur.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_colorSpill.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_composite.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_curves.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_defocus.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_dilate.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_displace.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_filter.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_flip.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_idMask.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_image.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_mapUV.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_mapValue.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_math.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_normal.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_rgb.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_rotate.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_scale.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_sepcombHSVA.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_sepcombRGBA.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_sepcombYCCA.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_sepcombYUVA.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_splitViewer.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_texture.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_translate.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_valToRgb.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_value.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_vecBlur.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_viewer.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_util.c [new file with mode: 0644]
source/blender/nodes/intern/CMP_util.h [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_camera.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_curves.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_geom.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_mapping.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_material.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_math.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_normal.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_output.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_rgb.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_texture.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_value.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_util.c [new file with mode: 0644]
source/blender/nodes/intern/SHD_util.h [new file with mode: 0644]

diff --git a/source/blender/nodes/CMP_node.h b/source/blender/nodes/CMP_node.h
new file mode 100644 (file)
index 0000000..64fcded
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef CMP_NODE_H
+#define CMP_NODE_H
+
+#include "BKE_node.h"
+
+#define CMP_FILT_SOFT          0
+#define CMP_FILT_SHARP         1
+#define CMP_FILT_LAPLACE       2
+#define CMP_FILT_SOBEL         3
+#define CMP_FILT_PREWITT       4
+#define CMP_FILT_KIRSCH                5
+#define CMP_FILT_SHADOW                6
+
+/* scale node type, in custom1 */
+#define CMP_SCALE_RELATIVE     0
+#define CMP_SCALE_ABSOLUTE     1
+
+/* ****************** types array for all composite nodes ****************** */
+
+extern bNodeType cmp_node_rlayers;
+extern bNodeType cmp_node_image;
+extern bNodeType cmp_node_texture;
+extern bNodeType cmp_node_value;
+extern bNodeType cmp_node_rgb;
+extern bNodeType cmp_node_curve_time;
+
+extern bNodeType cmp_node_composite;
+extern bNodeType cmp_node_viewer;
+extern bNodeType cmp_node_splitviewer;
+extern bNodeType cmp_node_output_file;
+
+extern bNodeType cmp_node_curve_rgb;
+extern bNodeType cmp_node_mix_rgb;
+extern bNodeType cmp_node_hue_sat;
+extern bNodeType cmp_node_alphaover;
+extern bNodeType cmp_node_zcombine;
+
+extern bNodeType cmp_node_normal;
+extern bNodeType cmp_node_curve_vec;
+extern bNodeType cmp_node_map_value;
+
+extern bNodeType cmp_node_filter;
+extern bNodeType cmp_node_blur;
+extern bNodeType cmp_node_vecblur;
+extern bNodeType cmp_node_dilateerode;
+extern bNodeType cmp_node_defocus;
+
+extern bNodeType cmp_node_valtorgb;
+extern bNodeType cmp_node_rgbtobw;     
+extern bNodeType cmp_node_setalpha;
+extern bNodeType cmp_node_idmask;
+extern bNodeType cmp_node_math;
+extern bNodeType cmp_node_seprgba;
+extern bNodeType cmp_node_combrgba;
+extern bNodeType cmp_node_sephsva;
+extern bNodeType cmp_node_combhsva;
+extern bNodeType cmp_node_sepyuva;
+extern bNodeType cmp_node_combyuva;
+extern bNodeType cmp_node_sepycca;
+extern bNodeType cmp_node_combycca; 
+
+extern bNodeType cmp_node_diff_matte;
+extern bNodeType cmp_node_chroma;
+extern bNodeType cmp_node_channel_matte;
+extern bNodeType cmp_node_color_spill;
+extern bNodeType cmp_node_luma_matte; 
+
+extern bNodeType cmp_node_translate;
+extern bNodeType cmp_node_rotate;
+extern bNodeType cmp_node_scale;
+extern bNodeType cmp_node_flip;
+extern bNodeType cmp_node_displace;
+extern bNodeType cmp_node_mapuv; 
+
+static bNodeType *node_all_composit[]= {
+   &node_group_typeinfo,
+
+      &cmp_node_rlayers,
+      &cmp_node_image,
+      &cmp_node_texture,
+      &cmp_node_value,
+      &cmp_node_rgb,
+      &cmp_node_curve_time,
+
+      &cmp_node_composite,
+      &cmp_node_viewer,
+      &cmp_node_splitviewer,
+      &cmp_node_output_file,
+
+      &cmp_node_curve_rgb,
+      &cmp_node_mix_rgb,
+      &cmp_node_hue_sat,
+      &cmp_node_alphaover,
+      &cmp_node_zcombine,
+
+      &cmp_node_normal,
+      &cmp_node_curve_vec,
+      &cmp_node_map_value,
+
+      &cmp_node_filter,
+      &cmp_node_blur,
+      &cmp_node_vecblur,
+      &cmp_node_dilateerode,
+      &cmp_node_defocus,
+
+      &cmp_node_valtorgb,
+      &cmp_node_rgbtobw,       
+      &cmp_node_setalpha,
+      &cmp_node_idmask,
+      &cmp_node_math,
+      &cmp_node_seprgba,
+      &cmp_node_combrgba,
+      &cmp_node_sephsva,
+      &cmp_node_combhsva,
+      &cmp_node_sepyuva,
+      &cmp_node_combyuva,
+      &cmp_node_sepycca,
+      &cmp_node_combycca,
+
+      &cmp_node_diff_matte,
+      &cmp_node_chroma,
+      &cmp_node_channel_matte,
+      &cmp_node_color_spill,
+      &cmp_node_luma_matte,
+
+      &cmp_node_translate,
+      &cmp_node_rotate,
+      &cmp_node_scale,
+      &cmp_node_flip,
+      &cmp_node_displace,
+      &cmp_node_mapuv,
+
+      NULL
+};
+
+#endif
diff --git a/source/blender/nodes/SHD_node.h b/source/blender/nodes/SHD_node.h
new file mode 100644 (file)
index 0000000..ec7446b
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef SHD_NODE_H
+#define SHD_NODE_H
+
+#include "BKE_node.h"
+
+/* custom defines options for Material node */
+#define SH_NODE_MAT_DIFF   1
+#define SH_NODE_MAT_SPEC   2
+#define SH_NODE_MAT_NEG    4
+
+
+/* the type definitions array */
+/* ****************** types array for all shaders ****************** */
+
+extern bNodeType sh_node_output;
+extern bNodeType sh_node_material;
+extern bNodeType sh_node_camera;
+extern bNodeType sh_node_value;
+extern bNodeType sh_node_rgb;
+extern bNodeType sh_node_mix_rgb;
+extern bNodeType sh_node_valtorgb;
+extern bNodeType sh_node_rgbtobw;
+extern bNodeType sh_node_texture;
+extern bNodeType sh_node_normal;
+extern bNodeType sh_node_geom;
+extern bNodeType sh_node_mapping;
+extern bNodeType sh_node_curve_vec;
+extern bNodeType sh_node_curve_rgb;
+extern bNodeType sh_node_math;
+extern bNodeType sh_node_vect_math;
+extern bNodeType sh_node_squeeze;
+
+static bNodeType *node_all_shaders[]= {
+   &node_group_typeinfo,
+      &sh_node_output,
+      &sh_node_material,
+      &sh_node_camera,
+      &sh_node_value,
+      &sh_node_rgb,
+      &sh_node_mix_rgb,
+      &sh_node_valtorgb,
+      &sh_node_rgbtobw,
+      &sh_node_texture,
+      &sh_node_normal,
+      &sh_node_geom,
+      &sh_node_mapping,
+      &sh_node_curve_vec,
+      &sh_node_curve_rgb,
+      &sh_node_math,
+      &sh_node_vect_math,
+      &sh_node_squeeze,
+      NULL
+};
+#endif
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c b/source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c
new file mode 100644 (file)
index 0000000..5bf193b
--- /dev/null
@@ -0,0 +1,133 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** ALPHAOVER ******************** */
+static bNodeSocketType cmp_node_alphaover_in[]= {
+       {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_alphaover_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_alphaover_premul(bNode *node, float *out, float *src, float *over, float *fac)
+{
+       
+       if(over[3]<=0.0f) {
+               QUATCOPY(out, src);
+       }
+       else if(*fac==1.0f && over[3]>=1.0f) {
+               QUATCOPY(out, over);
+       }
+       else {
+               float mul= 1.0f - *fac*over[3];
+
+               out[0]= (mul*src[0]) + *fac*over[0];
+               out[1]= (mul*src[1]) + *fac*over[1];
+               out[2]= (mul*src[2]) + *fac*over[2];
+               out[3]= (mul*src[3]) + *fac*over[3];
+       }       
+}
+
+/* result will be still premul, but the over part is premulled */
+static void do_alphaover_key(bNode *node, float *out, float *src, float *over, float *fac)
+{
+       
+       if(over[3]<=0.0f) {
+               QUATCOPY(out, src);
+       }
+       else if(*fac==1.0f && over[3]>=1.0f) {
+               QUATCOPY(out, over);
+       }
+       else {
+               float premul= fac[0]*over[3];
+               float mul= 1.0f - premul;
+
+               out[0]= (mul*src[0]) + premul*over[0];
+               out[1]= (mul*src[1]) + premul*over[1];
+               out[2]= (mul*src[2]) + premul*over[2];
+               out[3]= (mul*src[3]) + fac[0]*over[3];
+       }
+}
+
+
+static void node_composit_exec_alphaover(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order in: col col */
+       /* stack order out: col */
+       if(out[0]->hasoutput==0) 
+               return;
+       
+       /* input no image? then only color operation */
+       if(in[1]->data==NULL) {
+               do_alphaover_premul(node, out[0]->vec, in[1]->vec, in[2]->vec, in[0]->vec);
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= in[1]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+               
+               if(node->custom1)
+                       composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_key, CB_RGBA, CB_RGBA, CB_VAL);
+               else
+                       composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_premul, CB_RGBA, CB_RGBA, CB_VAL);
+               
+               out[0]->data= stackbuf;
+       }
+}
+
+static int node_composit_buts_alphaover(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+
+      /* alpha type */
+      uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "ConvertPremul",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 19, 
+         &node->custom1, 0, 0, 0, 0, "");
+   }
+   return 19;
+}
+
+bNodeType cmp_node_alphaover= {
+       /* type code   */       CMP_NODE_ALPHAOVER,
+       /* name        */       "AlphaOver",
+       /* width+range */       80, 40, 120,
+       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_alphaover_in,
+       /* output sock */       cmp_node_alphaover_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_alphaover,
+   /* butfunc     */ node_composit_buts_alphaover
+       
+};
\ No newline at end of file
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c
new file mode 100644 (file)
index 0000000..2002625
--- /dev/null
@@ -0,0 +1,663 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+
+/* **************** BLUR ******************** */
+static bNodeSocketType cmp_node_blur_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Size",                  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_blur_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static float *make_gausstab(int filtertype, int rad)
+{
+       float *gausstab, sum, val;
+       int i, n;
+       
+       n = 2 * rad + 1;
+       
+       gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
+       
+       sum = 0.0f;
+       for (i = -rad; i <= rad; i++) {
+               val= RE_filter_value(filtertype, (float)i/(float)rad);
+               sum += val;
+               gausstab[i+rad] = val;
+       }
+       
+       sum= 1.0f/sum;
+       for(i=0; i<n; i++)
+               gausstab[i]*= sum;
+       
+       return gausstab;
+}
+
+static float *make_bloomtab(int rad)
+{
+       float *bloomtab, val;
+       int i, n;
+       
+       n = 2 * rad + 1;
+       
+       bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom");
+       
+       for (i = -rad; i <= rad; i++) {
+               val = pow(1.0 - fabs((float)i)/((float)rad), 4.0);
+               bloomtab[i+rad] = val;
+       }
+       
+       return bloomtab;
+}
+
+/* both input images of same type, either 4 or 1 channel */
+static void blur_single_image(CompBuf *new, CompBuf *img, float scale, NodeBlurData *nbd)
+{
+       CompBuf *work;
+       register float sum, val;
+       float rval, gval, bval, aval;
+       float *gausstab, *gausstabcent;
+       int rad, imgx= img->x, imgy= img->y;
+       int x, y, pix= img->type;
+       int i, bigstep;
+       float *src, *dest;
+
+       /* helper image */
+       work= alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */
+       
+       /* horizontal */
+       rad = scale*(float)nbd->sizex;
+       if(rad>imgx/2)
+               rad= imgx/2;
+       else if(rad<1) 
+               rad= 1;
+
+       gausstab= make_gausstab(nbd->filtertype, rad);
+       gausstabcent= gausstab+rad;
+       
+       for (y = 0; y < imgy; y++) {
+               float *srcd= img->rect + pix*(y*img->x);
+               
+               dest = work->rect + pix*(y * img->x);
+               
+               for (x = 0; x < imgx ; x++) {
+                       int minr= x-rad<0?-x:-rad;
+                       int maxr= x+rad>imgx?imgx-x:rad;
+                       
+                       src= srcd + pix*(x+minr);
+                       
+                       sum= gval = rval= bval= aval= 0.0f;
+                       for (i= minr; i < maxr; i++) {
+                               val= gausstabcent[i];
+                               sum+= val;
+                               rval += val * (*src++);
+                               if(pix==4) {
+                                       gval += val * (*src++);
+                                       bval += val * (*src++);
+                                       aval += val * (*src++);
+                               }
+                       }
+                       sum= 1.0f/sum;
+                       *dest++ = rval*sum;
+                       if(pix==4) {
+                               *dest++ = gval*sum;
+                               *dest++ = bval*sum;
+                               *dest++ = aval*sum;
+                       }
+               }
+       }
+       
+       /* vertical */
+       MEM_freeN(gausstab);
+       
+       rad = scale*(float)nbd->sizey;
+       if(rad>imgy/2)
+               rad= imgy/2;
+       else if(rad<1) 
+               rad= 1;
+
+       gausstab= make_gausstab(nbd->filtertype, rad);
+       gausstabcent= gausstab+rad;
+       
+       bigstep = pix*imgx;
+       for (x = 0; x < imgx; x++) {
+               float *srcd= work->rect + pix*x;
+               
+               dest = new->rect + pix*x;
+               
+               for (y = 0; y < imgy ; y++) {
+                       int minr= y-rad<0?-y:-rad;
+                       int maxr= y+rad>imgy?imgy-y:rad;
+                       
+                       src= srcd + bigstep*(y+minr);
+                       
+                       sum= gval = rval= bval= aval= 0.0f;
+                       for (i= minr; i < maxr; i++) {
+                               val= gausstabcent[i];
+                               sum+= val;
+                               rval += val * src[0];
+                               if(pix==4) {
+                                       gval += val * src[1];
+                                       bval += val * src[2];
+                                       aval += val * src[3];
+                               }
+                               src += bigstep;
+                       }
+                       sum= 1.0f/sum;
+                       dest[0] = rval*sum;
+                       if(pix==4) {
+                               dest[1] = gval*sum;
+                               dest[2] = bval*sum;
+                               dest[3] = aval*sum;
+                       }
+                       dest+= bigstep;
+               }
+       }
+       
+       free_compbuf(work);
+       MEM_freeN(gausstab);
+}
+
+/* reference has to be mapped 0-1, and equal in size */
+static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, float fac, NodeBlurData *nbd)
+{
+       CompBuf *wbuf;
+       register float val;
+       float radxf, radyf;
+       float **maintabs;
+       float *gausstabx, *gausstabcenty;
+       float *gausstaby, *gausstabcentx;
+       int radx, rady, imgx= img->x, imgy= img->y;
+       int x, y;
+       int i, j;
+       float *src, *dest, *wb;
+       
+       wbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
+       
+       /* horizontal */
+       radx = (float)nbd->sizex;
+       if(radx>imgx/2)
+               radx= imgx/2;
+       else if(radx<1) 
+               radx= 1;
+       
+       /* vertical */
+       rady = (float)nbd->sizey;
+       if(rady>imgy/2)
+               rady= imgy/2;
+       else if(rady<1) 
+               rady= 1;
+       
+       x= MAX2(radx, rady);
+       maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
+       for(i= 0; i<x; i++)
+               maintabs[i]= make_bloomtab(i+1);
+               
+       /* vars to store before we go */
+//     refd= ref->rect;
+       src= img->rect;
+       
+       radxf= (float)radx;
+       radyf= (float)rady;
+       
+       for (y = 0; y < imgy; y++) {
+               for (x = 0; x < imgx ; x++, src+=4) {//, refd++) {
+                       
+//                     int refradx= (int)(refd[0]*radxf);
+//                     int refrady= (int)(refd[0]*radyf);
+                       
+                       int refradx= (int)(radxf*0.3f*src[3]*(src[0]+src[1]+src[2]));
+                       int refrady= (int)(radyf*0.3f*src[3]*(src[0]+src[1]+src[2]));
+                       
+                       if(refradx>radx) refradx= radx;
+                       else if(refradx<1) refradx= 1;
+                       if(refrady>rady) refrady= rady;
+                       else if(refrady<1) refrady= 1;
+                       
+                       if(refradx==1 && refrady==1) {
+                               wb= wbuf->rect + ( y*imgx + x);
+                               dest= new->rect + 4*( y*imgx + x);
+                               wb[0]+= 1.0f;
+                               dest[0] += src[0];
+                               dest[1] += src[1];
+                               dest[2] += src[2];
+                               dest[3] += src[3];
+                       }
+                       else {
+                               int minxr= x-refradx<0?-x:-refradx;
+                               int maxxr= x+refradx>imgx?imgx-x:refradx;
+                               int minyr= y-refrady<0?-y:-refrady;
+                               int maxyr= y+refrady>imgy?imgy-y:refrady;
+                               
+                               float *destd= new->rect + 4*( (y + minyr)*imgx + x + minxr);
+                               float *wbufd= wbuf->rect + ( (y + minyr)*imgx + x + minxr);
+                               
+                               gausstabx= maintabs[refradx-1];
+                               gausstabcentx= gausstabx+refradx;
+                               gausstaby= maintabs[refrady-1];
+                               gausstabcenty= gausstaby+refrady;
+                               
+                               for (i= minyr; i < maxyr; i++, destd+= 4*imgx, wbufd+= imgx) {
+                                       dest= destd;
+                                       wb= wbufd;
+                                       for (j= minxr; j < maxxr; j++, dest+=4, wb++) {
+                                               
+                                               val= gausstabcenty[i]*gausstabcentx[j];
+                                               wb[0]+= val;
+                                               dest[0] += val * src[0];
+                                               dest[1] += val * src[1];
+                                               dest[2] += val * src[2];
+                                               dest[3] += val * src[3];
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       x= imgx*imgy;
+       dest= new->rect;
+       wb= wbuf->rect;
+       while(x--) {
+               val= 1.0f/wb[0];
+               dest[0]*= val;
+               dest[1]*= val;
+               dest[2]*= val;
+               dest[3]*= val;
+               wb++;
+               dest+= 4;
+       }
+       
+       free_compbuf(wbuf);
+       
+       x= MAX2(radx, rady);
+       for(i= 0; i<x; i++)
+               MEM_freeN(maintabs[i]);
+       MEM_freeN(maintabs);
+       
+}
+
+#if 0
+static float hexagon_filter(float fi, float fj)
+{
+       fi= fabs(fi);
+       fj= fabs(fj);
+       
+       if(fj>0.33f) {
+               fj= (fj-0.33f)/0.66f;
+               if(fi+fj>1.0f)
+                       return 0.0f;
+               else
+                       return 1.0f;
+       }
+       else return 1.0f;
+}
+#endif
+
+/* uses full filter, no horizontal/vertical optimize possible */
+/* both images same type, either 1 or 4 channels */
+static void bokeh_single_image(CompBuf *new, CompBuf *img, float fac, NodeBlurData *nbd)
+{
+       register float val;
+       float radxf, radyf;
+       float *gausstab, *dgauss;
+       int radx, rady, imgx= img->x, imgy= img->y;
+       int x, y, pix= img->type;
+       int i, j, n;
+       float *src= NULL, *dest, *srcd= NULL;
+       
+       /* horizontal */
+       radxf = fac*(float)nbd->sizex;
+       if(radxf>imgx/2.0f)
+               radxf= imgx/2.0f;
+       else if(radxf<1.0f) 
+               radxf= 1.0f;
+       
+       /* vertical */
+       radyf = fac*(float)nbd->sizey;
+       if(radyf>imgy/2.0f)
+               radyf= imgy/2.0f;
+       else if(radyf<1.0f) 
+               radyf= 1.0f;
+       
+       radx= ceil(radxf);
+       rady= ceil(radyf);
+       
+       n = (2*radx+1)*(2*rady+1);
+       
+       /* create a full filter image */
+       gausstab= MEM_mallocN(sizeof(float)*n, "filter tab");
+       dgauss= gausstab;
+       val= 0.0f;
+       for(j=-rady; j<=rady; j++) {
+               for(i=-radx; i<=radx; i++, dgauss++) {
+                       float fj= (float)j/radyf;
+                       float fi= (float)i/radxf;
+                       float dist= sqrt(fj*fj + fi*fi);
+                       
+               //*dgauss= hexagon_filter(fi, fj);
+                       *dgauss= RE_filter_value(nbd->filtertype, 2.0f*dist - 1.0f);
+
+                       val+= *dgauss;
+               }
+       }
+
+       if(val!=0.0f) {
+               val= 1.0f/val;
+               for(j= n -1; j>=0; j--)
+                       gausstab[j]*= val;
+       }
+       else gausstab[4]= 1.0f;
+       
+       for (y = -rady+1; y < imgy+rady-1; y++) {
+               
+               if(y<=0) srcd= img->rect;
+               else if(y<imgy) srcd+= pix*imgx;
+               else srcd= img->rect + pix*(imgy-1)*imgx;
+                       
+               for (x = -radx+1; x < imgx+radx-1 ; x++) {
+                       int minxr= x-radx<0?-x:-radx;
+                       int maxxr= x+radx>=imgx?imgx-x-1:radx;
+                       int minyr= y-rady<0?-y:-rady;
+                       int maxyr= y+rady>imgy-1?imgy-y-1:rady;
+                       
+                       float *destd= new->rect + pix*( (y + minyr)*imgx + x + minxr);
+                       float *dgausd= gausstab + (minyr+rady)*2*radx + minxr+radx;
+                       
+                       if(x<=0) src= srcd;
+                       else if(x<imgx) src+= pix;
+                       else src= srcd + pix*(imgx-1);
+                       
+                       for (i= minyr; i <=maxyr; i++, destd+= pix*imgx, dgausd+= 2*radx + 1) {
+                               dest= destd;
+                               dgauss= dgausd;
+                               for (j= minxr; j <=maxxr; j++, dest+=pix, dgauss++) {
+                                       val= *dgauss;
+                                       if(val!=0.0f) {
+                                               dest[0] += val * src[0];
+                                               if(pix>1) {
+                                                       dest[1] += val * src[1];
+                                                       dest[2] += val * src[2];
+                                                       dest[3] += val * src[3];
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       MEM_freeN(gausstab);
+}
+
+
+/* reference has to be mapped 0-1, and equal in size */
+static void blur_with_reference(CompBuf *new, CompBuf *img, CompBuf *ref, NodeBlurData *nbd)
+{
+       CompBuf *blurbuf, *ref_use;
+       register float sum, val;
+       float rval, gval, bval, aval, radxf, radyf;
+       float **maintabs;
+       float *gausstabx, *gausstabcenty;
+       float *gausstaby, *gausstabcentx;
+       int radx, rady, imgx= img->x, imgy= img->y;
+       int x, y, pix= img->type;
+       int i, j;
+       float *src, *dest, *refd, *blurd;
+
+       if(ref->x!=img->x && ref->y!=img->y)
+               return;
+       
+       ref_use= typecheck_compbuf(ref, CB_VAL);
+       
+       /* trick is; we blur the reference image... but only works with clipped values*/
+       blurbuf= alloc_compbuf(imgx, imgy, CB_VAL, 1);
+       blurd= blurbuf->rect;
+       refd= ref_use->rect;
+       for(x= imgx*imgy; x>0; x--, refd++, blurd++) {
+               if(refd[0]<0.0f) blurd[0]= 0.0f;
+               else if(refd[0]>1.0f) blurd[0]= 1.0f;
+               else blurd[0]= refd[0];
+       }
+       
+       blur_single_image(blurbuf, blurbuf, 1.0f, nbd);
+       
+       /* horizontal */
+       radx = (float)nbd->sizex;
+       if(radx>imgx/2)
+               radx= imgx/2;
+       else if(radx<1) 
+               radx= 1;
+       
+       /* vertical */
+       rady = (float)nbd->sizey;
+       if(rady>imgy/2)
+               rady= imgy/2;
+       else if(rady<1) 
+               rady= 1;
+       
+       x= MAX2(radx, rady);
+       maintabs= MEM_mallocN(x*sizeof(void *), "gauss array");
+       for(i= 0; i<x; i++)
+               maintabs[i]= make_gausstab(nbd->filtertype, i+1);
+       
+       refd= blurbuf->rect;
+       dest= new->rect;
+       radxf= (float)radx;
+       radyf= (float)rady;
+       
+       for (y = 0; y < imgy; y++) {
+               for (x = 0; x < imgx ; x++, dest+=pix, refd++) {
+                       int refradx= (int)(refd[0]*radxf);
+                       int refrady= (int)(refd[0]*radyf);
+                       
+                       if(refradx>radx) refradx= radx;
+                       else if(refradx<1) refradx= 1;
+                       if(refrady>rady) refrady= rady;
+                       else if(refrady<1) refrady= 1;
+
+                       if(refradx==1 && refrady==1) {
+                               src= img->rect + pix*( y*imgx + x);
+                               if(pix==1)
+                                       dest[0]= src[0];
+                               else
+                                       QUATCOPY(dest, src);
+                       }
+                       else {
+                               int minxr= x-refradx<0?-x:-refradx;
+                               int maxxr= x+refradx>imgx?imgx-x:refradx;
+                               int minyr= y-refrady<0?-y:-refrady;
+                               int maxyr= y+refrady>imgy?imgy-y:refrady;
+       
+                               float *srcd= img->rect + pix*( (y + minyr)*imgx + x + minxr);
+                               
+                               gausstabx= maintabs[refradx-1];
+                               gausstabcentx= gausstabx+refradx;
+                               gausstaby= maintabs[refrady-1];
+                               gausstabcenty= gausstaby+refrady;
+
+                               sum= gval = rval= bval= aval= 0.0f;
+                               
+                               for (i= minyr; i < maxyr; i++, srcd+= pix*imgx) {
+                                       src= srcd;
+                                       for (j= minxr; j < maxxr; j++, src+=pix) {
+                                       
+                                               val= gausstabcenty[i]*gausstabcentx[j];
+                                               sum+= val;
+                                               rval += val * src[0];
+                                               if(pix>1) {
+                                                       gval += val * src[1];
+                                                       bval += val * src[2];
+                                                       aval += val * src[3];
+                                               }
+                                       }
+                               }
+                               sum= 1.0f/sum;
+                               dest[0] = rval*sum;
+                               if(pix>1) {
+                                       dest[1] = gval*sum;
+                                       dest[2] = bval*sum;
+                                       dest[3] = aval*sum;
+                               }
+                       }
+               }
+       }
+       
+       free_compbuf(blurbuf);
+       
+       x= MAX2(radx, rady);
+       for(i= 0; i<x; i++)
+               MEM_freeN(maintabs[i]);
+       MEM_freeN(maintabs);
+       
+       if(ref_use!=ref)
+               free_compbuf(ref_use);
+}
+
+
+
+static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       CompBuf *new, *img= in[0]->data;
+       
+       if(img==NULL || out[0]->hasoutput==0)
+               return;
+       
+       if(img->type==CB_VEC2 || img->type==CB_VEC3) {
+               img= typecheck_compbuf(in[0]->data, CB_RGBA);
+       }
+       
+       /* if fac input, we do it different */
+       if(in[1]->data) {
+               
+               /* make output size of input image */
+               new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
+               
+               /* accept image offsets from other nodes */
+               new->xof = img->xof;
+               new->yof = img->yof;
+               
+               blur_with_reference(new, img, in[1]->data, node->storage);
+               
+               out[0]->data= new;
+       }
+       else {
+               
+               if(in[1]->vec[0]<=0.001f) {     /* time node inputs can be a tiny value */
+                       new= pass_on_compbuf(img);
+               }
+               else {
+                       NodeBlurData *nbd= node->storage;
+                       CompBuf *gammabuf;
+                       
+                       /* make output size of input image */
+                       new= alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
+                       
+                       /* accept image offsets from other nodes */
+                       new->xof = img->xof;
+                       new->yof = img->yof;
+                               
+                       if(nbd->gamma) {
+                               gammabuf= dupalloc_compbuf(img);
+                               gamma_correct_compbuf(gammabuf, 0);
+                       }
+                       else gammabuf= img;
+                       
+                       if(nbd->bokeh)
+                               bokeh_single_image(new, gammabuf, in[1]->vec[0], nbd);
+                       else if(1)
+                               blur_single_image(new, gammabuf, in[1]->vec[0], nbd);
+                       else    /* bloom experimental... */
+                               bloom_with_reference(new, gammabuf, NULL, in[1]->vec[0], nbd);
+                       
+                       if(nbd->gamma) {
+                               gamma_correct_compbuf(new, 1);
+                               free_compbuf(gammabuf);
+                       }
+               }
+               out[0]->data= new;
+       }
+       if(img!=in[0]->data)
+               free_compbuf(img);
+}
+
+static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      NodeBlurData *nbd= node->storage;
+      uiBut *bt;
+      short dy= butr->ymin+38;
+      short dx= (butr->xmax-butr->xmin)/2;
+      char str[256];
+
+      uiBlockBeginAlign(block);
+      sprintf(str, "Filter Type%%t|Flat %%x%d|Tent %%x%d|Quad %%x%d|Cubic %%x%d|Gauss %%x%d|CatRom %%x%d|Mitch %%x%d", R_FILTER_BOX, R_FILTER_TENT, R_FILTER_QUAD, R_FILTER_CUBIC, R_FILTER_GAUSS, R_FILTER_CATROM, R_FILTER_MITCH);
+      uiDefButS(block, MENU, B_NODE_EXEC+node->nr,str,         
+         butr->xmin, dy, dx*2, 19, 
+         &nbd->filtertype, 0, 0, 0, 0, "Set sampling filter for blur");
+      dy-=19;            
+      uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Bokeh",             
+         butr->xmin, dy, dx, 19, 
+         &nbd->bokeh, 0, 0, 0, 0, "Uses circular filter, warning it's slow!");
+      uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Gamma",             
+         butr->xmin+dx, dy, dx, 19, 
+         &nbd->gamma, 0, 0, 0, 0, "Applies filter on gamma corrected values");
+
+      dy-=19;
+      bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:",
+         butr->xmin, dy, dx, 19, 
+         &nbd->sizex, 0, 256, 0, 0, "");
+      bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:",
+         butr->xmin+dx, dy, dx, 19, 
+         &nbd->sizey, 0, 256, 0, 0, "");
+   }
+   return 57;
+}
+
+static void node_composit_init_blur(bNode* node)
+{
+   node->storage= MEM_callocN(sizeof(NodeBlurData), "node blur data");
+}
+
+bNodeType cmp_node_blur= {
+   /* type code   */   CMP_NODE_BLUR,
+   /* name        */   "Blur",
+   /* width+range */   120, 80, 200,
+   /* class+opts  */   NODE_CLASS_OP_FILTER, NODE_OPTIONS,
+   /* input sock  */   cmp_node_blur_in,
+   /* output sock */   cmp_node_blur_out,
+   /* storage     */   "NodeBlurData",
+   /* execfunc    */   node_composit_exec_blur,
+   /* butfunc     */ node_composit_buts_blur,
+                     node_composit_init_blur
+};
\ No newline at end of file
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c
new file mode 100644 (file)
index 0000000..4f74f31
--- /dev/null
@@ -0,0 +1,260 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* ******************* Channel Matte Node ********************************* */
+static bNodeSocketType cmp_node_channel_matte_in[]={
+       {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_channel_matte_out[]={
+       {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static void do_normalized_rgba_to_ycca2(bNode *node, float *out, float *in)
+{
+       /*normalize to the range 0.0 to 1.0) */
+       rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       out[0]=(out[0])/255.0;
+       out[1]=(out[1])/255.0;
+       out[2]=(out[2])/255.0;
+       out[3]=in[3];
+}
+
+static void do_normalized_ycca_to_rgba2(bNode *node, float *out, float *in)
+{
+       /*un-normalize the normalize from above */
+       in[0]=in[0]*255.0;
+       in[1]=in[1]*255.0;
+       in[2]=in[2]*255.0;
+       ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       out[3]=in[3];
+}
+
+
+static void do_channel_matte(bNode *node, float *out, float *in)
+{
+       NodeChroma *c=(NodeChroma *)node->storage;
+       float alpha=0.0;
+       
+       /* Alpha=G-MAX(R, B) */
+       
+       switch(node->custom2)
+       {
+       case 1:
+               {
+                       alpha=in[0]-MAX2(in[1],in[2]);
+                       break;
+               }
+       case 2:
+               {
+                       alpha=in[1]-MAX2(in[0],in[2]);
+                       break;
+               }
+       case 3:
+               {
+                       alpha=in[2]-MAX2(in[0],in[1]);
+                       break;
+               }
+       default:
+               break;
+       }
+       
+       /*flip because 0.0 is transparent, not 1.0*/
+       alpha=1-alpha;
+       
+       /* test range*/
+       if(alpha>c->t1) {
+               alpha=in[3]; /*whatever it was prior */
+       }
+       else if(alpha<c->t2){
+               alpha=0.0;
+       }
+       else {/*blend */
+               alpha=(alpha-c->t2)/(c->t1-c->t2);
+       }
+
+       
+       /* don't make something that was more transparent less transparent */
+       if (alpha<in[3]) {
+               out[3]=alpha;
+       }
+       else {
+               out[3]=in[3];
+       }
+
+}
+
+static void node_composit_exec_channel_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       CompBuf *cbuf;
+       CompBuf *outbuf;
+       
+       if(in[0]->hasinput==0)  return;
+       if(in[0]->data==NULL) return;
+       if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
+       
+       cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
+       
+       outbuf=dupalloc_compbuf(cbuf);
+       
+       /*convert to colorspace*/
+       switch(node->custom1) {
+       case 1: /*RGB */
+               break;
+       case 2: /*HSV*/
+               composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_hsva, CB_RGBA);
+               break;
+       case 3: /*YUV*/
+               composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA);
+               break;
+       case 4: /*YCC*/
+               composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_normalized_rgba_to_ycca2, CB_RGBA);
+               break;
+       default:
+               break;
+       }
+
+       /*use the selected channel information to do the key */
+       composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_channel_matte, CB_RGBA);
+
+       /*convert back to RGB colorspace in place*/
+       switch(node->custom1) {
+       case 1: /*RGB*/
+               break;
+       case 2: /*HSV*/
+               composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_hsva_to_rgba, CB_RGBA);
+               break;
+       case 3: /*YUV*/
+               composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA);
+               break;
+       case 4: /*YCC*/
+               composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_normalized_ycca_to_rgba2, CB_RGBA);
+               break;
+       default:
+               break;
+       }
+
+       generate_preview(node, outbuf);
+       out[0]->data=outbuf;
+       if(out[1]->hasoutput)
+               out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A);
+       
+       if(cbuf!=in[0]->data)
+               free_compbuf(cbuf);
+
+}
+
+static int node_composit_buts_channel_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      short sx= (butr->xmax-butr->xmin)/4;
+      short cx= (butr->xmax-butr->xmin)/3;
+      NodeChroma *c=node->storage;
+      char *c1, *c2, *c3;
+
+      /*color space selectors*/
+      uiBlockBeginAlign(block);
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"RGB",
+         butr->xmin,butr->ymin+60,sx,20,&node->custom1,1,1, 0, 0, "RGB Color Space");
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"HSV",
+         butr->xmin+sx,butr->ymin+60,sx,20,&node->custom1,1,2, 0, 0, "HSV Color Space");
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YUV",
+         butr->xmin+2*sx,butr->ymin+60,sx,20,&node->custom1,1,3, 0, 0, "YUV Color Space");
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YCC",
+         butr->xmin+3*sx,butr->ymin+60,sx,20,&node->custom1,1,4, 0, 0, "YCbCr Color Space");
+
+      if (node->custom1==1) {
+         c1="R"; c2="G"; c3="B";
+      }
+      else if(node->custom1==2){
+         c1="H"; c2="S"; c3="V";
+      }
+      else if(node->custom1==3){
+         c1="Y"; c2="U"; c3="V";
+      }
+      else { // if(node->custom1==4){
+         c1="Y"; c2="Cb"; c3="Cr";
+      }
+
+      /*channel selector */
+      uiDefButS(block, ROW, B_NODE_EXEC+node->nr, c1,
+         butr->xmin,butr->ymin+40,cx,20,&node->custom2,1, 1, 0, 0, "Channel 1");
+      uiDefButS(block, ROW, B_NODE_EXEC+node->nr, c2,
+         butr->xmin+cx,butr->ymin+40,cx,20,&node->custom2,1, 2, 0, 0, "Channel 2");
+      uiDefButS(block, ROW, B_NODE_EXEC+node->nr, c3,
+         butr->xmin+cx+cx,butr->ymin+40,cx,20,&node->custom2, 1, 3, 0, 0, "Channel 3");
+
+      /*tolerance sliders */
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "High ", 
+         butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+         &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque");
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Low ", 
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+         &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed");
+      uiBlockEndAlign(block);
+
+      /*keep t2 (low) less than t1 (high) */
+      if(c->t2 > c->t1) {
+         c->t2=c->t1;
+      }
+   }
+   return 80;
+}
+
+static void node_composit_init_channel_matte(bNode *node)
+{
+   NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+   node->storage=c;
+   c->t1= 0.0f;
+   c->t2= 0.0f;
+   c->t3= 0.0f;
+   c->fsize= 0.0f;
+   c->fstrength= 0.0f;
+   node->custom1= 1; /* RGB channel */
+   node->custom2= 2; /* Green Channel */
+}
+
+bNodeType cmp_node_channel_matte={
+   /* type code   */       CMP_NODE_CHANNEL_MATTE,
+   /* name        */       "Channel Key",
+   /* width+range */       200, 80, 250,
+   /* class+opts  */       NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
+   /* input sock  */       cmp_node_channel_matte_in,
+   /* output sock */       cmp_node_channel_matte_out,
+   /* storage     */       "NodeChroma",
+   /* execfunc    */       node_composit_exec_channel_matte,
+   /* butfunc     */       node_composit_buts_channel_matte,
+                           node_composit_init_channel_matte
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c
new file mode 100644 (file)
index 0000000..662c62a
--- /dev/null
@@ -0,0 +1,216 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* ******************* Chroma Key ********************************************************** */
+static bNodeSocketType cmp_node_chroma_in[]={
+       {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {SOCK_RGBA,1,"Key Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_chroma_out[]={
+       {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static void do_rgba_to_ycca_normalized(bNode *node, float *out, float *in)
+{
+       /*normalize to the range -1.0 to 1.0) */
+       rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       out[0]=((out[0])-16)/255.0;
+       out[1]=((out[1])-128)/255.0;
+       out[2]=((out[2])-128)/255.0;
+       out[3]=in[3];
+}
+
+static void do_ycca_to_rgba_normalized(bNode *node, float *out, float *in)
+{
+       /*un-normalize the normalize from above */
+       in[0]=(in[0]*255.0)+16;
+       in[1]=(in[1]*255.0)+128;
+       in[2]=(in[2]*255.0)+128;
+       ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       out[3]=in[3];
+}
+
+static void do_chroma_key(bNode *node, float *out, float *in)
+{
+       NodeChroma *c;
+       float x, z, alpha;
+       float theta, beta, angle;
+       float kfg, newY, newCb, newCr;
+
+       c=node->storage;
+
+       /* Algorithm from book "Video Demistified" */
+
+       /* find theta, the angle that the color space should be rotated based on key*/
+       theta=atan2(c->key[2],c->key[1]);
+
+       /*rotate the cb and cr into x/z space */
+       x=in[1]*cos(theta)+in[2]*sin(theta);
+       z=in[2]*cos(theta)-in[1]*sin(theta);
+
+       /*if within the acceptance angle */
+       angle=c->t1*M_PI/180.0; /* convert to radians */
+       
+       /* if kfg is <0 then the pixel is outside of the key color */
+       kfg=x-(fabs(z)/tan(angle/2.0));
+
+       if(kfg>0.0) {  /* found a pixel that is within key color */
+
+               newY=in[0]-(1-c->t3)*kfg;
+               newCb=in[1]-kfg*cosf(theta);
+               newCr=in[2]-kfg*sinf(theta);
+               alpha=(kfg+c->fsize)*(c->fstrength);
+
+               beta=atan2(newCr,newCb);
+               beta=beta*180.0/M_PI; /* convert to degrees for compare*/
+
+               /* if beta is within the clippin angle */
+               if(fabs(beta)<(c->t2/2.0)) {
+                       newCb=0.0;
+                       newCr=0.0;
+                       alpha=0.0;
+               }
+
+               out[0]=newY;
+               out[1]=newCb;
+               out[2]=newCr;
+
+               /* don't make something that was more transparent less transparent */
+               if (alpha<in[3]) {
+                       out[3]=alpha;
+               }
+               else {
+                       out[3]=in[3];
+               }
+       }
+       else { /*pixel is outside key color */
+               out[0]=in[0];
+               out[1]=in[1];
+               out[2]=in[2];
+               out[3]=in[3]; /* make pixel just as transparent as it was before */
+       }
+}
+
+static void node_composit_exec_chroma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       CompBuf *cbuf;
+       CompBuf *chromabuf;
+       NodeChroma *c;
+       
+       if(in[0]->hasinput==0) return;
+       if(in[0]->data==NULL) return;
+       if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
+       
+       cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+       
+       chromabuf= dupalloc_compbuf(cbuf);
+       
+       c=node->storage;
+       
+       /*convert rgbbuf to normalized chroma space*/
+       composit1_pixel_processor(node, chromabuf, cbuf, in[0]->vec, do_rgba_to_ycca_normalized, CB_RGBA);
+       /*convert key to normalized chroma color space */
+       do_rgba_to_ycca_normalized(node, c->key, in[1]->vec);
+       
+       /*per pixel chroma key*/
+       composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_chroma_key, CB_RGBA);
+       
+       /*convert back*/
+       composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_ycca_to_rgba_normalized, CB_RGBA);
+       
+       out[0]->data= chromabuf;
+       if(out[1]->hasoutput)
+               out[1]->data= valbuf_from_rgbabuf(chromabuf, CHAN_A);
+       
+       generate_preview(node, chromabuf);
+
+       if(cbuf!=in[0]->data)
+               free_compbuf(cbuf);
+};
+
+static int node_composit_buts_chroma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      short dx=(butr->xmax-butr->xmin)/2;
+      NodeChroma *c= node->storage;
+      uiBlockBeginAlign(block);
+
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Acceptance ",
+         butr->xmin, butr->ymin+60, butr->xmax-butr->xmin, 20,
+         &c->t1, 1.0f, 80.0f, 100, 0, "Tolerance for colors to be considered a keying color");
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Cutoff ",
+         butr->xmin, butr->ymin+40, butr->xmax-butr->xmin, 20,
+         &c->t2, 0.0f, 30.0f, 100, 0, "Colors below this will be considered as exact matches for keying color");
+
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Lift ",
+         butr->xmin, butr->ymin+20, dx, 20,
+         &c->fsize, 0.0f, 1.0f, 100, 0, "Alpha Lift");
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Gain ",
+         butr->xmin+dx, butr->ymin+20, dx, 20,
+         &c->fstrength, 0.0f, 1.0f, 100, 0, "Alpha Gain");
+
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Shadow Adjust ",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+         &c->t3, 0.0f, 1.0f, 100, 0, "Adjusts the brightness of any shadows captured");
+
+      if(c->t2 > c->t1)
+         c->t2=c->t1;
+   }
+   return 80;
+}
+
+static void node_composit_init_chroma_matte(bNode *node)
+{
+   NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+   node->storage= c;
+   c->t1= 30.0f;
+   c->t2= 10.0f;
+   c->t3= 0.0f;
+   c->fsize= 0.0f;
+   c->fstrength= 1.0f;
+};
+
+bNodeType cmp_node_chroma={
+   /* type code   */       CMP_NODE_CHROMA,
+   /* name        */       "Chroma Key",
+   /* width+range */       200, 80, 300,
+   /* class+opts  */       NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
+   /* input sock  */       cmp_node_chroma_in,
+   /* output sock */       cmp_node_chroma_out,
+   /* storage     */       "NodeChroma",
+   /* execfunc    */       node_composit_exec_chroma_matte,
+   /* butfunc     */       node_composit_buts_chroma_matte,
+                           node_composit_init_chroma_matte
+};
\ No newline at end of file
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_colorSpill.c b/source/blender/nodes/intern/CMP_nodes/CMP_colorSpill.c
new file mode 100644 (file)
index 0000000..b82b4af
--- /dev/null
@@ -0,0 +1,164 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include "../CMP_util.h"
+
+
+/* ******************* Color Spill Supression ********************************* */
+static bNodeSocketType cmp_node_color_spill_in[]={
+       {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_color_spill_out[]={
+       {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static void do_reduce_red(bNode *node, float* out, float *in)
+{
+       NodeChroma *c;
+       c=node->storage;
+       
+       if(in[0] > in[1] && in[0] > in[2]) {
+               out[0]=((in[1]+in[2])/2)*(1-c->t1);
+       }
+}
+
+static void do_reduce_green(bNode *node, float* out, float *in)
+{
+       NodeChroma *c;
+       c=node->storage;
+       
+       if(in[1] > in[0] && in[1] > in[2]) {
+               out[1]=((in[0]+in[2])/2)*(1-c->t1);
+       }
+}
+
+static void do_reduce_blue(bNode *node, float* out, float *in)
+{
+       NodeChroma *c;
+       c=node->storage;
+       
+       if(in[2] > in[1] && in[2] > in[1]) {
+               out[2]=((in[1]+in[0])/2)*(1-c->t1);
+       }
+}
+
+static void node_composit_exec_color_spill(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /*
+       Originally based on the information from the book "The Art and Science of Digital Composition" and 
+       discussions from vfxtalk.com.*/
+       CompBuf *cbuf;
+       CompBuf *rgbbuf;
+       
+       if(out[0]->hasoutput==0 || in[0]->hasinput==0) return;
+       if(in[0]->data==NULL) return;
+       
+       cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
+       rgbbuf=dupalloc_compbuf(cbuf);
+
+       switch(node->custom1)
+       {
+       case 1:  /*red spill*/
+               {
+                       composit1_pixel_processor(node, rgbbuf, cbuf, in[1]->vec, do_reduce_red, CB_RGBA);
+                       break;
+               }
+       case 2: /*green spill*/
+               {
+                       composit1_pixel_processor(node, rgbbuf, cbuf, in[1]->vec, do_reduce_green, CB_RGBA);
+                       break;
+               }
+       case 3: /*blue spill*/
+               {
+                       composit1_pixel_processor(node, rgbbuf, cbuf, in[1]->vec, do_reduce_blue, CB_RGBA);
+                       break;
+               }
+       default:
+               break;
+       }
+
+       out[0]->data=rgbbuf;
+
+       if(cbuf!=in[0]->data)
+               free_compbuf(cbuf);
+}
+
+static int node_composit_buts_color_spill(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      short dx= (butr->xmax-butr->xmin)/3;
+
+      NodeChroma *c=node->storage;
+      uiBlockBeginAlign(block);
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Enhance: ", 
+         butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+         &c->t1, 0.0f, 0.5f, 100, 2, "Adjusts how much selected channel is affected by color spill algorithm");
+      uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "R",
+         butr->xmin,butr->ymin,dx,20,
+         &node->custom1,1,1, 0, 0, "Red Spill Suppression");
+      uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "G",
+         butr->xmin+dx,butr->ymin,dx,20,
+         &node->custom1,1,2, 0, 0, "Green Spill Suppression");
+      uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "B",
+         butr->xmin+2*dx,butr->ymin,dx,20,
+         &node->custom1, 1, 3, 0, 0, "Blue Spill Suppression");
+      uiBlockEndAlign(block);
+   }
+   return 60;
+}
+
+static void node_composit_init_color_spill(bNode *node)
+{
+   NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+   node->storage=c;
+   c->t1= 0.0f;
+   c->t2= 0.0f;
+   c->t3= 0.0f;
+   c->fsize= 0.0f;
+   c->fstrength= 0.0f;
+   node->custom1= 2; /* green channel */
+};
+
+bNodeType cmp_node_color_spill={
+   /* type code   */       CMP_NODE_COLOR_SPILL,
+   /* name        */       "Color Spill",
+   /* width+range */       140, 80, 200,
+   /* class+opts  */       NODE_CLASS_MATTE, NODE_OPTIONS,
+   /* input sock  */       cmp_node_color_spill_in,
+   /* output sock */       cmp_node_color_spill_out,
+   /* storage     */       "NodeChroma",
+   /* execfunc    */       node_composit_exec_color_spill,
+   /* butfunc     */       node_composit_buts_color_spill,
+                           node_composit_init_color_spill
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_composite.c b/source/blender/nodes/intern/CMP_nodes/CMP_composite.c
new file mode 100644 (file)
index 0000000..1ea7565
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+
+/* **************** COMPOSITE ******************** */
+static bNodeSocketType cmp_node_composite_in[]= {
+       {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+/* applies to render pipeline */
+static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* image assigned to output */
+       /* stack order input sockets: col, alpha, z */
+       
+       if(node->flag & NODE_DO_OUTPUT) {       /* only one works on out */
+               RenderData *rd= data;
+               if(rd->scemode & R_DOCOMP) {
+                       RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); /* G.scene is WEAK! */
+                       if(rr) {
+                               CompBuf *outbuf, *zbuf=NULL;
+                               
+                               if(rr->rectf) 
+                                       MEM_freeN(rr->rectf);
+                               outbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 1);
+                               
+                               if(in[1]->data==NULL)
+                                       composit1_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA);
+                               else
+                                       composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
+                               
+                               if(in[2]->data) {
+                                       if(rr->rectz) 
+                                               MEM_freeN(rr->rectz);
+                                       zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1);
+                                       composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL);
+                                       rr->rectz= zbuf->rect;
+                                       zbuf->malloc= 0;
+                                       free_compbuf(zbuf);
+                               }
+                               generate_preview(node, outbuf);
+                               
+                               /* we give outbuf to rr... */
+                               rr->rectf= outbuf->rect;
+                               outbuf->malloc= 0;
+                               free_compbuf(outbuf);
+                               
+                               /* signal for imageviewer to refresh (it converts to byte rects...) */
+                               BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
+                               return;
+                       }
+               }
+       }
+       if(in[0]->data)
+               generate_preview(node, in[0]->data);
+}
+
+bNodeType cmp_node_composite= {
+       /* type code   */       CMP_NODE_COMPOSITE,
+       /* name        */       "Composite",
+       /* width+range */       80, 60, 200,
+       /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
+       /* input sock  */       cmp_node_composite_in,
+       /* output sock */       NULL,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_composite,
+   /* butfunc     */ NULL
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_curves.c b/source/blender/nodes/intern/CMP_nodes/CMP_curves.c
new file mode 100644 (file)
index 0000000..23da03d
--- /dev/null
@@ -0,0 +1,223 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** CURVE Time  ******************** */
+
+/* custom1 = sfra, custom2 = efra */
+static bNodeSocketType cmp_node_time_out[]= {
+       {       SOCK_VALUE, 0, "Fac",   1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_curves_time(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order output: fac */
+       float fac= 0.0f;
+       
+       if(node->custom1 < node->custom2)
+               fac= (G.scene->r.cfra - node->custom1)/(float)(node->custom2-node->custom1);
+       
+       fac= curvemapping_evaluateF(node->storage, 0, fac);
+       out[0]->vec[0]= CLAMPIS(fac, 0.0f, 1.0f);
+}
+
+
+static int node_composit_buts_curves_time(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      CurveMapping *cumap= node->storage;
+      short dx= (butr->xmax-butr->xmin)/2;
+      rctf *curvebutr;
+
+      memcpy(&curvebutr, &butr, sizeof(rctf));
+      curvebutr->ymin += 26;
+
+      curvemap_buttons(block, node->storage, 's', B_NODE_EXEC+node->nr, B_REDR, curvebutr);
+
+      cumap->flag |= CUMA_DRAW_CFRA;
+      if(node->custom1<node->custom2)
+         cumap->black[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
+
+      uiBlockBeginAlign(block);
+      uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Sta:",
+         butr->xmin, butr->ymin-22, dx, 19, 
+         &node->custom1, 1.0, 20000.0, 0, 0, "Start frame");
+      uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "End:",
+         butr->xmin+dx, butr->ymin-22, dx, 19, 
+         &node->custom2, 1.0, 20000.0, 0, 0, "End frame");
+
+   }
+
+   return node->width-NODE_DY;
+};
+
+static void node_composit_init_curves_time(bNode* node)
+{
+   node->custom1= G.scene->r.sfra;
+   node->custom2= G.scene->r.efra;
+   node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+}
+
+bNodeType cmp_node_curve_time= {
+       /* type code   */       CMP_NODE_TIME,
+       /* name        */       "Time",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
+       /* input sock  */       NULL,
+       /* output sock */       cmp_node_time_out,
+       /* storage     */       "CurveMapping",
+       /* execfunc    */       node_composit_exec_curves_time,
+   /* butfunc     */ node_composit_buts_curves_time,
+                     node_composit_init_curves_time
+};
+
+
+
+/* **************** CURVE VEC  ******************** */
+static bNodeSocketType cmp_node_curve_vec_in[]= {
+       {       SOCK_VECTOR, 1, "Vector",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketType cmp_node_curve_vec_out[]= {
+       {       SOCK_VECTOR, 0, "Vector",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_curve_vec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order input:  vec */
+       /* stack order output: vec */
+       
+       curvemapping_evaluate_premulRGBF(node->storage, out[0]->vec, in[0]->vec);
+};
+
+static void node_composit_init_curve_vec(bNode* node)
+{
+   node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
+};
+
+bNodeType cmp_node_curve_vec= {
+       /* type code   */       CMP_NODE_CURVE_VEC,
+       /* name        */       "Vector Curves",
+       /* width+range */       200, 140, 320,
+       /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_curve_vec_in,
+       /* output sock */       cmp_node_curve_vec_out,
+       /* storage     */       "CurveMapping",
+       /* execfunc    */       node_composit_exec_curve_vec,
+   /* butfunc     */ node_buts_curvevec,
+                     node_composit_init_curve_vec
+       
+};
+
+/* **************** CURVE RGB  ******************** */
+static bNodeSocketType cmp_node_curve_rgb_in[]= {
+       {       SOCK_VALUE, 1, "Fac",   1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Image",  0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketType cmp_node_curve_rgb_out[]= {
+       {       SOCK_RGBA, 0, "Image",  0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_curves(bNode *node, float *out, float *in)
+{
+       curvemapping_evaluate_premulRGBF(node->storage, out, in);
+       out[3]= in[3];
+}
+
+static void do_curves_fac(bNode *node, float *out, float *in, float *fac)
+{
+       
+       if(*fac>=1.0)
+               curvemapping_evaluate_premulRGBF(node->storage, out, in);
+       else if(*fac<=0.0) {
+               VECCOPY(out, in);
+       }
+       else {
+               float col[4], mfac= 1.0f-*fac;
+               curvemapping_evaluate_premulRGBF(node->storage, col, in);
+               out[0]= mfac*in[0] + *fac*col[0];
+               out[1]= mfac*in[1] + *fac*col[1];
+               out[2]= mfac*in[2] + *fac*col[2];
+       }
+       out[3]= in[3];
+}
+
+static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order input:  fac, image */
+       /* stack order output: image */
+       
+       if(out[0]->hasoutput==0)
+               return;
+
+       /* input no image? then only color operation */
+       if(in[1]->data==NULL) {
+               curvemapping_evaluateRGBF(node->storage, out[0]->vec, in[1]->vec);
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= in[1]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+               
+               if(in[0]->data)
+                       composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac, CB_RGBA, CB_VAL);
+               else
+                       composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA);
+               
+               out[0]->data= stackbuf;
+       }
+       
+};
+
+static void node_composit_init_curve_rgb(bNode* node)
+{
+   node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
+};
+
+bNodeType cmp_node_curve_rgb= {
+       /* type code   */       CMP_NODE_CURVE_RGB,
+       /* name        */       "RGB Curves",
+       /* width+range */       200, 140, 320,
+       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_curve_rgb_in,
+       /* output sock */       cmp_node_curve_rgb_out,
+       /* storage     */       "CurveMapping",
+       /* execfunc    */       node_composit_exec_curve_rgb,
+   /* butfunc     */ node_buts_curvecol,
+                     node_composit_init_curve_rgb      
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c b/source/blender/nodes/intern/CMP_nodes/CMP_defocus.c
new file mode 100644 (file)
index 0000000..157b84a
--- /dev/null
@@ -0,0 +1,875 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* ************ qdn: Defocus node ****************** */
+static bNodeSocketType cmp_node_defocus_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Z",                     0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_defocus_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+
+// line coefs for point sampling & scancon. data.
+typedef struct BokehCoeffs {
+       float x0, y0, dx, dy;
+       float ls_x, ls_y;
+       float min_x, min_y, max_x, max_y;
+} BokehCoeffs;
+
+// returns array of BokehCoeffs
+// returns length of array in 'len_bkh',
+// radius squared of inscribed disk in 'inradsq', needed in getWeight() test,
+// BKH[8] is the data returned for the bokeh shape & bkh_b[4] is it's 2d bound
+static void makeBokeh(char bktype, char ro, int* len_bkh, float* inradsq, BokehCoeffs BKH[8], float bkh_b[4])
+{
+       float x0, x1, y0, y1, dx, dy, iDxy, w = ro*M_PI/180.f;
+       float wi = (360.f/bktype)*M_PI/180.f;
+       int i, ov, nv;
+       
+       // bktype must be at least 3 & <= 8
+       bktype = (bktype<3) ? 3 : ((bktype>8) ? 8 : bktype);
+       *len_bkh = bktype;
+       *inradsq = -1.f;
+
+       for (i=0; i<(*len_bkh); i++) {
+               x0 = cos(w);
+               y0 = sin(w);
+               w += wi;
+               x1 = cos(w);
+               y1 = sin(w);
+               if ((*inradsq)<0.f) {
+                       // radius squared of inscribed disk
+                       float idx=(x0+x1)*0.5f, idy=(y0+y1)*0.5f;
+                       *inradsq = idx*idx + idy*idy;
+               }
+               BKH[i].x0 = x0;
+               BKH[i].y0 = y0;
+               dx = x1-x0, dy = y1-y0;
+               iDxy = 1.f / sqrt(dx*dx + dy*dy);
+               dx *= iDxy;
+               dy *= iDxy;
+               BKH[i].dx = dx;
+               BKH[i].dy = dy;
+       }
+
+       // precalc scanconversion data
+       // bokeh bound, not transformed, for scanconvert
+       bkh_b[0] = bkh_b[2] = 1e10f;    // xmin/ymin
+       bkh_b[1] = bkh_b[3] = -1e10f;   // xmax/ymax
+       ov = (*len_bkh) - 1;
+       for (nv=0; nv<(*len_bkh); nv++) {
+               bkh_b[0] = MIN2(bkh_b[0], BKH[nv].x0);  // xmin
+               bkh_b[1] = MAX2(bkh_b[1], BKH[nv].x0);  // xmax
+               bkh_b[2] = MIN2(bkh_b[2], BKH[nv].y0);  // ymin
+               bkh_b[3] = MAX2(bkh_b[3], BKH[nv].y0);  // ymax
+               BKH[nv].min_x = MIN2(BKH[ov].x0, BKH[nv].x0);
+               BKH[nv].max_x = MAX2(BKH[ov].x0, BKH[nv].x0);
+               BKH[nv].min_y = MIN2(BKH[ov].y0, BKH[nv].y0);
+               BKH[nv].max_y = MAX2(BKH[ov].y0, BKH[nv].y0);
+               dy = BKH[nv].y0 - BKH[ov].y0;
+               BKH[nv].ls_x = (BKH[nv].x0 - BKH[ov].x0) / ((dy==0.f) ? 1.f : dy);
+               BKH[nv].ls_y = (BKH[nv].ls_x==0.f) ? 1.f : (1.f/BKH[nv].ls_x);
+               ov = nv;
+       }
+}
+
+// test if u/v inside shape & returns weight value
+static float getWeight(BokehCoeffs* BKH, int len_bkh, float u, float v, float rad, float inradsq)
+{
+       BokehCoeffs* bc = BKH;
+       float cdist, irad = (rad==0.f) ? 1.f : (1.f/rad);
+       u *= irad;
+       v *= irad;
+       // early out test1: if point outside outer unit disk, it cannot be inside shape
+       cdist = u*u + v*v;
+       if (cdist>1.f) return 0.f;
+       
+       // early out test2: if point inside or on inner disk, point must be inside shape
+       if (cdist<=inradsq) return 1.f;
+       
+       while (len_bkh--) {
+               if ((bc->dy*(u - bc->x0) - bc->dx*(v - bc->y0)) > 0.f) return 0.f;
+               bc++;
+       }
+       return 1.f;
+}
+
+// QMC.seq. for sampling, A.Keller, EMS
+static float RI_vdC(unsigned int bits, unsigned int r)
+{
+       bits = ( bits << 16) | ( bits >> 16);
+       bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8);
+       bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4);
+       bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2);
+       bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1);
+       bits ^= r;
+       return (float)((double)bits / 4294967296.0);
+}
+
+// single channel IIR gaussian filtering
+// much faster than anything else, constant time independent of width
+// should extend to multichannel and make this a node, could be useful
+static void IIR_gauss(CompBuf* buf, float sigma)
+{
+       double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
+       float *X, *Y, *W;
+       int i, x, y, sz;
+
+       // single channel only for now
+       if (buf->type != CB_VAL) return;
+
+       // <0.5 not valid, though can have a possibly useful sort of sharpening effect
+       if (sigma < 0.5) return;
+       
+       // see "Recursive Gabor Filtering" by Young/VanVliet
+       // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200
+       if (sigma >= 3.556)
+               q = 0.9804*(sigma - 3.556) + 2.5091;
+       else // sigma >= 0.5
+               q = (0.0561*sigma + 0.5784)*sigma - 0.2568;
+       q2 = q*q;
+       sc = (1.1668 + q)*(3.203729649  + (2.21566 + q)*q);
+       // no gabor filtering here, so no complex multiplies, just the regular coefs.
+       // all negated here, so as not to have to recalc Triggs/Sdika matrix
+       cf[1] = q*(5.788961737 + (6.76492 + 3.0*q)*q)/ sc;
+       cf[2] = -q2*(3.38246 + 3.0*q)/sc;
+       // 0 & 3 unchanged
+       cf[3] = q2*q/sc;
+       cf[0] = 1.0 - cf[1] - cf[2] - cf[3];
+
+       // Triggs/Sdika border corrections,
+       // it seems to work, not entirely sure if it is actually totally correct,
+       // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark),
+       // found one other implementation by Cristoph Lampert,
+       // but neither seem to be quite the same, result seems to be ok sofar anyway.
+       // Extra scale factor here to not have to do it in filter,
+       // though maybe this had something to with the precision errors
+       sc = cf[0]/((1.0 + cf[1] - cf[2] + cf[3])*(1.0 - cf[1] - cf[2] - cf[3])*(1.0 + cf[2] + (cf[1] - cf[3])*cf[3]));
+       tsM[0] = sc*(-cf[3]*cf[1] + 1.0 - cf[3]*cf[3] - cf[2]);
+       tsM[1] = sc*((cf[3] + cf[1])*(cf[2] + cf[3]*cf[1]));
+       tsM[2] = sc*(cf[3]*(cf[1] + cf[3]*cf[2]));
+       tsM[3] = sc*(cf[1] + cf[3]*cf[2]);
+       tsM[4] = sc*(-(cf[2] - 1.0)*(cf[2] + cf[3]*cf[1]));
+       tsM[5] = sc*(-(cf[3]*cf[1] + cf[3]*cf[3] + cf[2] - 1.0)*cf[3]);
+       tsM[6] = sc*(cf[3]*cf[1] + cf[2] + cf[1]*cf[1] - cf[2]*cf[2]);
+       tsM[7] = sc*(cf[1]*cf[2] + cf[3]*cf[2]*cf[2] - cf[1]*cf[3]*cf[3] - cf[3]*cf[3]*cf[3] - cf[3]*cf[2] + cf[3]);
+       tsM[8] = sc*(cf[3]*(cf[1] + cf[3]*cf[2]));
+
+#define YVV(L)\
+{\
+       W[0] = cf[0]*X[0] + cf[1]*X[0] + cf[2]*X[0] + cf[3]*X[0];\
+       W[1] = cf[0]*X[1] + cf[1]*W[0] + cf[2]*X[0] + cf[3]*X[0];\
+       W[2] = cf[0]*X[2] + cf[1]*W[1] + cf[2]*W[0] + cf[3]*X[0];\
+       for (i=3; i<L; i++)\
+               W[i] = cf[0]*X[i] + cf[1]*W[i-1] + cf[2]*W[i-2] + cf[3]*W[i-3];\
+       tsu[0] = W[L-1] - X[L-1];\
+       tsu[1] = W[L-2] - X[L-1];\
+       tsu[2] = W[L-3] - X[L-1];\
+       tsv[0] = tsM[0]*tsu[0] + tsM[1]*tsu[1] + tsM[2]*tsu[2] + X[L-1];\
+       tsv[1] = tsM[3]*tsu[0] + tsM[4]*tsu[1] + tsM[5]*tsu[2] + X[L-1];\
+       tsv[2] = tsM[6]*tsu[0] + tsM[7]*tsu[1] + tsM[8]*tsu[2] + X[L-1];\
+       Y[L-1] = cf[0]*W[L-1] + cf[1]*tsv[0] + cf[2]*tsv[1] + cf[3]*tsv[2];\
+       Y[L-2] = cf[0]*W[L-2] + cf[1]*Y[L-1] + cf[2]*tsv[0] + cf[3]*tsv[1];\
+       Y[L-3] = cf[0]*W[L-3] + cf[1]*Y[L-2] + cf[2]*Y[L-1] + cf[3]*tsv[0];\
+       for (i=L-4; i>=0; i--)\
+               Y[i] = cf[0]*W[i] + cf[1]*Y[i+1] + cf[2]*Y[i+2] + cf[3]*Y[i+3];\
+}
+
+       // intermediate buffers
+       sz = MAX2(buf->x, buf->y);
+       Y = MEM_callocN(sz*sizeof(float), "IIR_gauss Y buf");
+       W = MEM_callocN(sz*sizeof(float), "IIR_gauss W buf");
+       // H
+       for (y=0; y<buf->y; y++) {
+               X = &buf->rect[y*buf->x];
+               YVV(buf->x);
+               memcpy(X, Y, sizeof(float)*buf->x);
+       }
+       // V
+       X = MEM_callocN(buf->y*sizeof(float), "IIR_gauss X buf");
+       for (x=0; x<buf->x; x++) {
+               for (y=0; y<buf->y; y++)
+                       X[y] = buf->rect[x + y*buf->x];
+               YVV(buf->y);
+               for (y=0; y<buf->y; y++)
+                       buf->rect[x + y*buf->x] = Y[y];
+       }
+       MEM_freeN(X);
+
+       MEM_freeN(W);
+       MEM_freeN(Y);
+#undef YVV
+}
+
+static void defocus_blur(CompBuf* new, CompBuf* img, CompBuf* zbuf, float inpval, NodeDefocus* nqd)
+{
+       CompBuf *wts;   // weights buffer
+       CompBuf *crad;  // CoC radius buffer
+       BokehCoeffs BKH[8];     // bokeh shape data, here never > 8 pts.
+       float bkh_b[4] = {0};   // shape 2D bound
+       unsigned int p, px, p4, zp, cp, cp4;
+       float *ctcol, u, v, iZ, ct_crad, bcrad, lwt, wt=0, cR2=0;
+       float dof_sp, maxfgc, nmaxc, scf, bk_hn_theta=0, inradsq=0;
+       float cam_fdist=1, cam_invfdist=1, cam_lens=35;
+       int x, y, sx, sy, len_bkh=0;
+       float aspect, aperture;
+       int minsz;
+       
+       // get some required params from the current scene camera
+       Object* camob = G.scene->camera;
+       if (camob && camob->type==OB_CAMERA) {
+               Camera* cam = (Camera*)camob->data;
+               cam_lens = cam->lens;
+               cam_fdist = (cam->YF_dofdist==0.f) ? 1e10f : cam->YF_dofdist;
+               cam_invfdist = 1.f/cam_fdist;
+       }
+
+       // guess work here.. best match with raytraced result
+       minsz = MIN2(img->x, img->y);
+       dof_sp = (float)minsz / (16.f / cam_lens);      // <- == aspect * MIN2(img->x, img->y) / tan(0.5f * fov);
+       
+       // aperture
+       aspect = (img->x > img->y) ? (img->y / (float)img->x) : (img->x / (float)img->y);
+       aperture = 0.5f*(cam_lens / (aspect*32.f)) / nqd->fstop;
+       
+       // if not disk, make bokeh coefficients and other needed data
+       if (nqd->bktype!=0) {
+               makeBokeh(nqd->bktype, nqd->rotation, &len_bkh, &inradsq, BKH, bkh_b);
+               bk_hn_theta = 0.5 * nqd->bktype * sin(2.0 * M_PI / nqd->bktype);        // weight factor
+       }
+       
+       // accumulated weights
+       wts = alloc_compbuf(img->x, img->y, CB_VAL, 1);
+       // CoC radius buffer
+       crad = alloc_compbuf(img->x, img->y, CB_VAL, 1);
+
+       // if 'no_zbuf' flag set (which is always set if input is not an image),
+       // values are instead interpreted directly as blur radius values
+       if (nqd->no_zbuf) {
+               // to prevent *reaaallly* big radius values and impossible calculation times,
+               // limit the maximum to half the image width or height, whichever is smaller
+               float maxr = 0.5f*(float)MIN2(img->x, img->y);
+               for (p=0; p<(unsigned int)(img->x*img->y); p++) {
+                       crad->rect[p] = zbuf ? (zbuf->rect[p]*nqd->scale) : inpval;
+                       // bug #5921, limit minimum
+                       crad->rect[p] = MAX2(1e-5f, crad->rect[p]);
+                       crad->rect[p] = MIN2(crad->rect[p], maxr);
+                       // if maxblur!=0, limit maximum
+                       if (nqd->maxblur != 0.f) crad->rect[p] = MIN2(crad->rect[p], nqd->maxblur);
+               }
+       }
+       else {
+               // actual zbuffer.
+               // separate foreground from background CoC's
+               // then blur background and blend in again with foreground,
+               // improves the 'blurred foreground overlapping in-focus midground' sharp boundary problem.
+               // wts buffer here used for blendmask
+               maxfgc = 0.f; // maximum foreground CoC radius
+               for (y=0; y<img->y; y++) {
+                       p = y * img->x;
+                       for (x=0; x<img->x; x++) {
+                               px = p + x;
+                               iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]);
+                               crad->rect[px] = 0.5f*(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f));
+                               if (crad->rect[px] <= 0.f) {
+                                       wts->rect[px] = 1.f;
+                                       crad->rect[px] = -crad->rect[px];
+                                       if (crad->rect[px] > maxfgc) maxfgc = crad->rect[px];
+                               }
+                               else crad->rect[px] = wts->rect[px] = 0;
+                       }
+               }
+               
+               // fast blur...
+               IIR_gauss(crad, 2.f*maxfgc);
+               IIR_gauss(wts, 2.f*maxfgc);
+               
+               // find new maximum to scale it back to original
+               // (could skip this, not strictly necessary, in general, difference is quite small, but just in case...)
+               nmaxc = 0;
+               for (p=0; p<(img->x*img->y); p++)
+                       if (crad->rect[p] > nmaxc) nmaxc = crad->rect[p];
+               // rescale factor
+               scf = (nmaxc==0.f) ? 1.f: (maxfgc / nmaxc);
+               
+               // and blend...
+               for (y=0; y<img->y; y++) {
+                       p = y*img->x;
+                       for (x=0; x<img->x; x++) {
+                               px = p + x;
+                               if (zbuf->rect[px]!=0.f) {
+                                       iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]);
+                                       bcrad = 0.5f*fabs(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f));
+                                       // scale crad back to original maximum and blend
+                                       crad->rect[px] = bcrad + wts->rect[px]*(scf*crad->rect[px] - bcrad);
+                                       if (crad->rect[px] < 0.01f) crad->rect[px] = 0.01f;
+                                       // if maxblur!=0, limit maximum
+                                       if (nqd->maxblur != 0.f) crad->rect[px] = MIN2(crad->rect[px], nqd->maxblur);
+                               }
+                               else crad->rect[px] = 0.f;
+                               // clear weights for next part
+                               wts->rect[px] = 0.f;
+                       }
+               }
+               
+       }
+
+       //------------------------------------------------------------------
+       // main loop
+       for (y=0; y<img->y; y++) {
+               // some sort of visual feedback would be nice, or at least this text in the renderwin header
+               // but for now just print some info in the console every 8 scanlines.
+               if (((y & 7)==0) || (y==(img->y-1))) {
+                       printf("\rdefocus: Processing Line %d of %d ... ", y+1, img->y);
+                       fflush(stdout);
+               }
+               zp = y * img->x;
+               for (x=0; x<img->x; x++) {
+                       cp = zp + x;
+                       cp4 = cp * img->type;
+
+                       // Circle of Confusion radius for current pixel
+                       cR2 = ct_crad = crad->rect[cp];
+                       // skip if zero (border render)
+                       if (ct_crad==0.f) {
+                               // related to bug #5921, forgot output image when skipping 0 radius values
+                               new->rect[cp4] = img->rect[cp4];
+                               if (new->type != CB_VAL) {
+                                       new->rect[cp4+1] = img->rect[cp4+1];
+                                       new->rect[cp4+2] = img->rect[cp4+2];
+                                       new->rect[cp4+3] = img->rect[cp4+3];
+                               }
+                               continue;
+                       }
+                       cR2 *= cR2;
+                       
+                       // pixel color
+                       ctcol = &img->rect[cp4];
+                       
+                       if (!nqd->preview) {
+                               int xs, xe, ys, ye;
+                               float lwt, wtcol[4] = {0}, aacol[4] = {0};
+
+                               // shape weight
+                               if (nqd->bktype==0)     // disk
+                                       wt = 1.f/((float)M_PI*cR2);
+                               else
+                                       wt = 1.f/(cR2*bk_hn_theta);
+
+                               // weighted color
+                               wtcol[0] = wt*ctcol[0];
+                               if (new->type != CB_VAL) {
+                                       wtcol[1] = wt*ctcol[1];
+                                       wtcol[2] = wt*ctcol[2];
+                                       wtcol[3] = wt*ctcol[3];
+                               }
+
+                               // macro for background blur overlap test
+                               // unfortunately, since this is done per pixel,
+                               // it has a very significant negative impact on processing time...
+                               // (eg. aa disk blur without test: 112 sec, vs with test: 176 sec...)
+                               // iff center blur radius > threshold
+                               // and if overlap pixel in focus, do nothing, else add color/weigbt
+                               // (threshold constant is dependant on amount of blur)
+                               #define TESTBG1(c, w) {\
+                                       if (ct_crad > nqd->bthresh) {\
+                                               if (crad->rect[p] > nqd->bthresh) {\
+                                                       new->rect[p] += c[0];\
+                                                       wts->rect[p] += w;\
+                                               }\
+                                       }\
+                                       else {\
+                                               new->rect[p] += c[0];\
+                                               wts->rect[p] += w;\
+                                       }\
+                               }
+                               #define TESTBG4(c, w) {\
+                                       if (ct_crad > nqd->bthresh) {\
+                                               if (crad->rect[p] > nqd->bthresh) {\
+                                                       new->rect[p4] += c[0];\
+                                                       new->rect[p4+1] += c[1];\
+                                                       new->rect[p4+2] += c[2];\
+                                                       new->rect[p4+3] += c[3];\
+                                                       wts->rect[p] += w;\
+                                               }\
+                                       }\
+                                       else {\
+                                               new->rect[p4] += c[0];\
+                                               new->rect[p4+1] += c[1];\
+                                               new->rect[p4+2] += c[2];\
+                                               new->rect[p4+3] += c[3];\
+                                               wts->rect[p] += w;\
+                                       }\
+                               }
+                               if (nqd->bktype == 0) {
+                                       // Disk
+                                       int _x, i, j, di;
+                                       float Dj, T;
+                                       // AA pixel
+                                       #define AAPIX(a, b) {\
+                                               int _ny = b;\
+                                               if ((_ny >= 0) && (_ny < new->y)) {\
+                                                       int _nx = a;\
+                                                       if ((_nx >=0) && (_nx < new->x)) {\
+                                                               p = _ny*new->x + _nx;\
+                                                               if (new->type==CB_VAL) {\
+                                                                       TESTBG1(aacol, lwt);\
+                                                               }\
+                                                               else {\
+                                                                       p4 = p * new->type;\
+                                                                       TESTBG4(aacol, lwt);\
+                                                               }\
+                                                       }\
+                                               }\
+                                       }
+                                       // circle scanline
+                                       #define CSCAN(a, b) {\
+                                               int _ny = y + b;\
+                                               if ((_ny >= 0) && (_ny < new->y)) {\
+                                                       xs = x - a + 1;\
+                                                       if (xs < 0) xs = 0;\
+                                                       xe = x + a;\
+                                                       if (xe > new->x) xe = new->x;\
+                                                       p = _ny*new->x + xs;\
+                                                       if (new->type==CB_VAL) {\
+                                                               for (_x=xs; _x<xe; _x++, p++) TESTBG1(wtcol, wt);\
+                                                       }\
+                                                       else {\
+                                                               p4 = p * new->type;\
+                                                               for (_x=xs; _x<xe; _x++, p++, p4+=new->type) TESTBG4(wtcol, wt);\
+                                                       }\
+                                               }\
+                                       }
+                                       i = ceil(ct_crad);
+                                       j = 0;
+                                       T = 0;
+                                       while (i > j) {
+                                               Dj = sqrt(cR2 - j*j);
+                                               Dj -= floor(Dj);
+                                               di = 0;
+                                               if (Dj > T) { i--;  di = 1; }
+                                               T = Dj;
+                                               aacol[0] = wtcol[0]*Dj;
+                                               if (new->type != CB_VAL) {
+                                                       aacol[1] = wtcol[1]*Dj;
+                                                       aacol[2] = wtcol[2]*Dj;
+                                                       aacol[3] = wtcol[3]*Dj;
+                                               }
+                                               lwt = wt*Dj;
+                                               if (i!=j) {
+                                                       // outer pixels
+                                                       AAPIX(x+j, y+i);
+                                                       AAPIX(x+j, y-i);
+                                                       if (j) {
+                                                               AAPIX(x-j, y+i); // BL
+                                                               AAPIX(x-j, y-i); // TL
+                                                       }
+                                                       if (di) { // only when i changed, interior of outer section
+                                                               CSCAN(j, i); // bottom
+                                                               CSCAN(j, -i); // top
+                                                       }
+                                               }
+                                               // lower mid section
+                                               AAPIX(x+i, y+j);
+                                               if (i) AAPIX(x-i, y+j);
+                                               CSCAN(i, j);
+                                               // upper mid section
+                                               if (j) {
+                                                       AAPIX(x+i, y-j);
+                                                       if (i) AAPIX(x-i, y-j);
+                                                       CSCAN(i, -j);
+                                               }
+                                               j++;
+                                       }
+                                       #undef CSCAN
+                                       #undef AAPIX
+                               }
+                               else {
+                                       // n-agonal
+                                       int ov, nv;
+                                       float mind, maxd, lwt;
+                                       ys = MAX2((int)floor(bkh_b[2]*ct_crad + y), 0);
+                                       ye = MIN2((int)ceil(bkh_b[3]*ct_crad + y), new->y - 1);
+                                       for (sy=ys; sy<=ye; sy++) {
+                                               float fxs = 1e10f, fxe = -1e10f;
+                                               float yf = (sy - y)/ct_crad;
+                                               int found = 0;
+                                               ov = len_bkh - 1;
+                                               mind = maxd = 0;
+                                               for (nv=0; nv<len_bkh; nv++) {
+                                                       if ((BKH[nv].max_y >= yf) && (BKH[nv].min_y <= yf)) {
+                                                               float tx = BKH[ov].x0 + BKH[nv].ls_x*(yf - BKH[ov].y0);
+                                                               if (tx < fxs) { fxs = tx;  mind = BKH[nv].ls_x; }
+                                                               if (tx > fxe) { fxe = tx;  maxd = BKH[nv].ls_x; }
+                                                               if (++found == 2) break;
+                                                       }
+                                                       ov = nv;
+                                               }
+                                               if (found) {
+                                                       fxs = fxs*ct_crad + x;
+                                                       fxe = fxe*ct_crad + x;
+                                                       xs = (int)floor(fxs), xe = (int)ceil(fxe);
+                                                       // AA hack for first and last x pixel, near vertical edges only
+                                                       if (fabs(mind) <= 1.f) {
+                                                               if ((xs >= 0) && (xs < new->x)) {
+                                                                       lwt = 1.f-(fxs - xs);
+                                                                       aacol[0] = wtcol[0]*lwt;
+                                                                       p = xs + sy*new->x;
+                                                                       if (new->type==CB_VAL) {
+                                                                               lwt *= wt;
+                                                                               TESTBG1(aacol, lwt);
+                                                                       }
+                                                                       else {
+                                                                               p4 = p * new->type;
+                                                                               aacol[1] = wtcol[1]*lwt;
+                                                                               aacol[2] = wtcol[2]*lwt;
+                                                                               aacol[3] = wtcol[3]*lwt;
+                                                                               lwt *= wt;
+                                                                               TESTBG4(aacol, lwt);
+                                                                       }
+                                                               }
+                                                       }
+                                                       if (fabs(maxd) <= 1.f) {
+                                                               if ((xe >= 0) && (xe < new->x)) {
+                                                                       lwt = 1.f-(xe - fxe);
+                                                                       aacol[0] = wtcol[0]*lwt;
+                                                                       p = xe + sy*new->x;
+                                                                       if (new->type==CB_VAL) {
+                                                                               lwt *= wt;
+                                                                               TESTBG1(aacol, lwt);
+                                                                       }
+                                                                       else {
+                                                                               p4 = p * new->type;
+                                                                               aacol[1] = wtcol[1]*lwt;
+                                                                               aacol[2] = wtcol[2]*lwt;
+                                                                               aacol[3] = wtcol[3]*lwt;
+                                                                               lwt *= wt;
+                                                                               TESTBG4(aacol, lwt);
+                                                                       }
+                                                               }
+                                                       }
+                                                       xs = MAX2(xs+1, 0);
+                                                       xe = MIN2(xe, new->x);
+                                                       // remaining interior scanline
+                                                       p = sy*new->x + xs;
+                                                       if (new->type==CB_VAL) {
+                                                               for (sx=xs; sx<xe; sx++, p++) TESTBG1(wtcol, wt);
+                                                       }
+                                                       else {
+                                                               p4 = p * new->type;
+                                                               for (sx=xs; sx<xe; sx++, p++, p4+=new->type) TESTBG4(wtcol, wt);
+                                                       }
+                                               }
+                                       }
+
+                                       // now traverse in opposite direction, y scanlines,
+                                       // but this time only draw the near horizontal edges,
+                                       // applying same AA hack as above
+                                       xs = MAX2((int)floor(bkh_b[0]*ct_crad + x), 0);
+                                       xe = MIN2((int)ceil(bkh_b[1]*ct_crad + x), img->x - 1);
+                                       for (sx=xs; sx<=xe; sx++) {
+                                               float xf = (sx - x)/ct_crad;
+                                               float fys = 1e10f, fye = -1e10f;
+                                               int found = 0;
+                                               ov = len_bkh - 1;
+                                               mind = maxd = 0;
+                                               for (nv=0; nv<len_bkh; nv++) {
+                                                       if ((BKH[nv].max_x >= xf) && (BKH[nv].min_x <= xf)) {
+                                                               float ty = BKH[ov].y0 + BKH[nv].ls_y*(xf - BKH[ov].x0);
+                                                               if (ty < fys) { fys = ty;  mind = BKH[nv].ls_y; }
+                                                               if (ty > fye) { fye = ty;  maxd = BKH[nv].ls_y; }
+                                                               if (++found == 2) break;
+                                                       }
+                                                       ov = nv;
+                                               }
+                                               if (found) {
+                                                       fys = fys*ct_crad + y;
+                                                       fye = fye*ct_crad + y;
+                                                       // near horizontal edges only, line slope <= 1
+                                                       if (fabs(mind) <= 1.f) {
+                                                               int iys = (int)floor(fys);
+                                                               if ((iys >= 0) && (iys < new->y)) {
+                                                                       lwt = 1.f - (fys - iys);
+                                                                       aacol[0] = wtcol[0]*lwt;
+                                                                       p = sx + iys*new->x;
+                                                                       if (new->type==CB_VAL) {
+                                                                               lwt *= wt;
+                                                                               TESTBG1(aacol, lwt);
+                                                                       }
+                                                                       else {
+                                                                               p4 = p * new->type;
+                                                                               aacol[1] = wtcol[1]*lwt;
+                                                                               aacol[2] = wtcol[2]*lwt;
+                                                                               aacol[3] = wtcol[3]*lwt;
+                                                                               lwt *= wt;
+                                                                               TESTBG4(aacol, lwt);
+                                                                       }
+                                                               }
+                                                       }
+                                                       if (fabs(maxd) <= 1.f) {
+                                                               int iye = ceil(fye);
+                                                               if ((iye >= 0) && (iye < new->y)) {
+                                                                       lwt = 1.f - (iye - fye);
+                                                                       aacol[0] = wtcol[0]*lwt;
+                                                                       p = sx + iye*new->x;
+                                                                       if (new->type==CB_VAL) {
+                                                                               lwt *= wt;
+                                                                               TESTBG1(aacol, lwt);
+                                                                       }
+                                                                       else {
+                                                                               p4 = p * new->type;
+                                                                               aacol[1] = wtcol[1]*lwt;
+                                                                               aacol[2] = wtcol[2]*lwt;
+                                                                               aacol[3] = wtcol[3]*lwt;
+                                                                               lwt *= wt;
+                                                                               TESTBG4(aacol, lwt);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                               }
+                               #undef TESTBG4
+                               #undef TESTBG1
+
+                       }
+                       else {
+                               // sampled, simple rejection sampling here, good enough
+                               unsigned int maxsam, s, ui = BLI_rand()*BLI_rand();
+                               float wcor, cpr = BLI_frand();
+                               if (nqd->no_zbuf)
+                                       maxsam = nqd->samples;  // no zbuffer input, use sample value directly
+                               else {
+                                       // depth adaptive sampling hack, the more out of focus, the more samples taken, 16 minimum.
+                                       maxsam = (int)(0.5f + nqd->samples*(1.f-(float)exp(-fabs(zbuf->rect[cp] - cam_fdist))));
+                                       if (maxsam < 16) maxsam = 16;
+                               }
+                               wcor = 1.f/(float)maxsam;
+                               for (s=0; s<maxsam; ++s) {
+                                       u = ct_crad*(2.f*RI_vdC(s, ui) - 1.f);
+                                       v = ct_crad*(2.f*(s + cpr)/(float)maxsam - 1.f);
+                                       sx = (int)(x + u + 0.5f), sy = (int)(y + v + 0.5f);
+                                       if ((sx<0) || (sx >= new->x) || (sy<0) || (sy >= new->y)) continue;
+                                       p = sx + sy*new->x;
+                                       p4 = p * new->type;
+                                       if (nqd->bktype==0)     // Disk
+                                               lwt = ((u*u + v*v)<=cR2) ? wcor : 0.f;
+                                       else    // AA not needed here
+                                               lwt = wcor * getWeight(BKH, len_bkh, u, v, ct_crad, inradsq);
+                                       // prevent background bleeding onto in-focus pixels, user-option
+                                       if (ct_crad > nqd->bthresh) {  // if center blur > threshold
+                                               if (crad->rect[p] > nqd->bthresh) { // if overlap pixel in focus, do nothing, else add color/weigbt
+                                                       new->rect[p4] += ctcol[0] * lwt;
+                                                       if (new->type != CB_VAL) {
+                                                               new->rect[p4+1] += ctcol[1] * lwt;
+                                                               new->rect[p4+2] += ctcol[2] * lwt;
+                                                               new->rect[p4+3] += ctcol[3] * lwt;
+                                                       }
+                                                       wts->rect[p] += lwt;
+                                               }
+                                       }
+                                       else {
+                                               new->rect[p4] += ctcol[0] * lwt;
+                                               if (new->type != CB_VAL) {
+                                                       new->rect[p4+1] += ctcol[1] * lwt;
+                                                       new->rect[p4+2] += ctcol[2] * lwt;
+                                                       new->rect[p4+3] += ctcol[3] * lwt;
+                                               }
+                                               wts->rect[p] += lwt;
+                                       }
+                               }
+                       }
+
+               }
+       }
+       
+       // finally, normalize
+       for (y=0; y<new->y; y++) {
+               p = y * new->x;
+               p4 = p * new->type;
+               for (x=0; x<new->x; x++) {
+                       float dv = (wts->rect[p]==0.f) ? 1.f : (1.f/wts->rect[p]);
+                       new->rect[p4] *= dv;
+                       if (new->type!=CB_VAL) {
+                               new->rect[p4+1] *= dv;
+                               new->rect[p4+2] *= dv;
+                               new->rect[p4+3] *= dv;
+                       }
+                       p++;
+                       p4 += new->type;
+               }
+       }
+
+       free_compbuf(crad);
+       free_compbuf(wts);
+       
+       printf("Done\n");
+}
+
+
+static void node_composit_exec_defocus(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       CompBuf *new, *old, *zbuf_use = NULL, *img = in[0]->data, *zbuf = in[1]->data;
+       NodeDefocus* nqd = node->storage;
+       
+       if ((img==NULL) || (out[0]->hasoutput==0)) return;
+       
+       // if image not valid type or fstop==infinite (128), nothing to do, pass in to out
+       if (((img->type!=CB_RGBA) && (img->type!=CB_VAL)) || ((nqd->no_zbuf==0) && (nqd->fstop==128.f))) {
+               new = alloc_compbuf(img->x, img->y, img->type, 0);
+               new->rect = img->rect;
+               out[0]->data = new;
+               return;
+       }
+       
+       if (zbuf!=NULL) {
+               // Zbuf input, check to make sure, single channel, same size
+               // doesn't have to be actual zbuffer, but must be value type
+               if ((zbuf->x != img->x) || (zbuf->y != img->y)) {
+                       // could do a scale here instead...
+                       printf("Z input must be same size as image !\n");
+                       return;
+               }
+               zbuf_use = typecheck_compbuf(zbuf, CB_VAL);
+       }
+       else nqd->no_zbuf = 1;  // no zbuffer input
+               
+       // ok, process
+       old = img;
+       if (nqd->gamco) {
+               // gamma correct, blender func is simplified, fixed value & RGBA only, should make user param
+               old = dupalloc_compbuf(img);
+               gamma_correct_compbuf(old, 0);
+       }
+       
+       new = alloc_compbuf(old->x, old->y, old->type, 1);
+       defocus_blur(new, old, zbuf_use, in[1]->vec[0]*nqd->scale, node->storage);
+       
+       if (nqd->gamco) {
+               gamma_correct_compbuf(new, 1);
+               free_compbuf(old);
+       }
+       
+       out[0]->data = new;
+       if (zbuf_use && (zbuf_use != zbuf)) free_compbuf(zbuf_use);
+}
+
+/* qdn: defocus node */
+static int node_composit_buts_defocus(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      NodeDefocus *nqd = node->storage;
+      short dy = butr->ymin + 209;
+      short dx = butr->xmax - butr->xmin; 
+      char* mstr1 = "Bokeh Type%t|Octagon %x8|Heptagon %x7|Hexagon %x6|Pentagon %x5|Square %x4|Triangle %x3|Disk %x0";
+
+      uiDefBut(block, LABEL, B_NOP, "Bokeh Type", butr->xmin, dy, dx, 19, NULL, 0, 0, 0, 0, "");
+      uiDefButC(block, MENU, B_NODE_EXEC+node->nr, mstr1,
+         butr->xmin, dy-19, dx, 19,
+         &nqd->bktype, 0, 0, 0, 0, "Bokeh type");
+      if (nqd->bktype) { /* for some reason rotating a disk doesn't seem to work... ;) */
+         uiDefButC(block, NUM, B_NODE_EXEC+node->nr, "Rotate:",
+            butr->xmin, dy-38, dx, 19,
+            &nqd->rotation, 0, 90, 0, 0, "Bokeh shape rotation offset in degrees");
+      }
+      uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Gamma Correct",
+         butr->xmin, dy-57, dx, 19,
+         &nqd->gamco, 0, 0, 0, 0, "Enable gamma correction before and after main process");
+      if (nqd->no_zbuf==0) {
+         // only needed for zbuffer input
+         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "fStop:",
+            butr->xmin, dy-76, dx, 19,
+            &nqd->fstop, 0.5, 128, 10, 0, "Amount of focal blur, 128=infinity=perfect focus, half the value doubles the blur radius");
+      }
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Maxblur:",
+         butr->xmin, dy-95, dx, 19,
+         &nqd->maxblur, 0, 10000, 1000, 0, "blur limit, maximum CoC radius, 0=no limit");
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "BThreshold:",
+         butr->xmin, dy-114, dx, 19,
+         &nqd->bthresh, 0, 100, 100, 0, "CoC radius threshold, prevents background bleed on in-focus midground, 0=off");
+      uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Preview",
+         butr->xmin, dy-142, dx, 19,
+         &nqd->preview, 0, 0, 0, 0, "Enable sampling mode, useful for preview when using low samplecounts");
+      if (nqd->preview) {
+         /* only visible when sampling mode enabled */
+         uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Samples:",
+            butr->xmin, dy-161, dx, 19,
+            &nqd->samples, 16, 256, 0, 0, "Number of samples (16=grainy, higher=less noise)");
+      }
+      uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "No zbuffer",
+         butr->xmin, dy-190, dx, 19,
+         &nqd->no_zbuf, 0, 0, 0, 0, "Enable when using an image as input instead of actual zbuffer (auto enabled if node not image based, eg. time node)");
+      if (nqd->no_zbuf) {
+         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Zscale:",
+            butr->xmin, dy-209, dx, 19,
+            &nqd->scale, 0, 1000, 100, 0, "Scales the Z input when not using a zbuffer, controls maximum blur designated by the color white or input value 1");
+      }
+   }
+   return 228;
+}
+
+static void node_composit_init_defocus(bNode* node)
+{
+   /* qdn: defocus node */
+   NodeDefocus *nbd = MEM_callocN(sizeof(NodeDefocus), "node defocus data");
+   nbd->bktype = 0;
+   nbd->rotation = 0.f;
+   nbd->preview = 1;
+   nbd->gamco = 0;
+   nbd->samples = 16;
+   nbd->fstop = 128.f;
+   nbd->maxblur = 0;
+   nbd->bthresh = 1.f;
+   nbd->scale = 1.f;
+   nbd->no_zbuf = 1;
+   node->storage = nbd;
+};
+
+bNodeType cmp_node_defocus = {
+       /* type code   */       CMP_NODE_DEFOCUS,
+       /* name        */       "Defocus",
+       /* width+range */       150, 120, 200,
+       /* class+opts  */       NODE_CLASS_OP_FILTER, NODE_OPTIONS,
+       /* input sock  */       cmp_node_defocus_in,
+       /* output sock */       cmp_node_defocus_out,
+       /* storage     */       "NodeDefocus",
+       /* execfunc    */       node_composit_exec_defocus,
+   /* butfunc     */ node_composit_buts_defocus,
+                     node_composit_init_defocus
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c
new file mode 100644 (file)
index 0000000..7276245
--- /dev/null
@@ -0,0 +1,257 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* ******************* channel Difference Matte ********************************* */
+static bNodeSocketType cmp_node_diff_matte_in[]={
+       {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {SOCK_RGBA,1,"Key Color", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_diff_matte_out[]={
+       {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+/* note, keyvals is passed on from caller as stack array */
+/* might have been nicer as temp struct though... */
+static void do_diff_matte(bNode *node, float *colorbuf, float *inbuf, float *keyvals)
+{
+       NodeChroma *c= (NodeChroma *)node->storage;
+       float *keymin= keyvals;
+       float *keymax= keyvals+3;
+       float *key=    keyvals+6;
+       float tolerance= keyvals[9];
+       float distance, alpha;
+       
+       /*process the pixel if it is close to the key or already transparent*/
+       if(((colorbuf[0]>keymin[0] && colorbuf[0]<keymax[0]) &&
+               (colorbuf[1]>keymin[1] && colorbuf[1]<keymax[1]) &&
+               (colorbuf[2]>keymin[2] && colorbuf[2]<keymax[2])) || inbuf[3]<1.0f) {
+               
+               /*true distance from key*/
+               distance= sqrt((colorbuf[0]-key[0])*(colorbuf[0]-key[0])+
+                                         (colorbuf[1]-key[1])*(colorbuf[1]-key[1])+
+                                         (colorbuf[2]-key[2])*(colorbuf[2]-key[2]));
+               
+               /*is it less transparent than the prevous pixel*/
+               alpha= distance/tolerance;
+               if(alpha > inbuf[3]) alpha= inbuf[3];
+               if(alpha > c->fstrength) alpha= 0.0f;
+               
+               /*clamp*/
+               if (alpha>1.0f) alpha=1.0f;
+               if (alpha<0.0f) alpha=0.0f;
+               
+               /*premultiplied picture*/
+               colorbuf[3]= alpha;
+       }
+       else {
+               /*foreground object*/
+               colorbuf[3]= inbuf[3];
+       }
+}
+
+static void node_composit_exec_diff_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /*
+       Losely based on the Sequencer chroma key plug-in, but enhanced to work in other color spaces and
+       uses a differnt difference function (suggested in forums of vfxtalk.com).
+       */
+       CompBuf *workbuf;
+       CompBuf *inbuf;
+       NodeChroma *c;
+       float keyvals[10];
+       float *keymin= keyvals;
+       float *keymax= keyvals+3;
+       float *key=    keyvals+6;
+       float *tolerance= keyvals+9;
+       float t[3];
+       
+       /*is anything connected?*/
+       if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
+       /*must have an image imput*/
+       if(in[0]->data==NULL) return;
+       
+       inbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
+       
+       c=node->storage;
+       workbuf=dupalloc_compbuf(inbuf);
+       
+       /*use the input color*/
+       key[0]= in[1]->vec[0];
+       key[1]= in[1]->vec[1];
+       key[2]= in[1]->vec[2];
+       
+       /*get the tolerances from the UI*/
+       t[0]=c->t1;
+       t[1]=c->t2;
+       t[2]=c->t3;
+       
+       /*convert to colorspace*/
+       switch(node->custom1) {
+               case 1: /*RGB*/
+                               break;
+               case 2: /*HSV*/
+               /*convert the key (in place)*/
+                       rgb_to_hsv(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
+                       composit1_pixel_processor(node, workbuf, inbuf, in[1]->vec, do_rgba_to_hsva, CB_RGBA);
+                       break;
+               case 3: /*YUV*/
+                       rgb_to_yuv(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
+                       composit1_pixel_processor(node, workbuf, inbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA);
+                       break;
+               case 4: /*YCC*/
+                       rgb_to_ycc(key[0], key[1], key[2], &key[0], &key[1], &key[2]);
+                       composit1_pixel_processor(node, workbuf, inbuf, in[1]->vec, do_rgba_to_ycca, CB_RGBA);
+                       /*account for ycc is on a 0..255 scale*/
+                       t[0]= c->t1*255.0;
+                       t[1]= c->t2*255.0;
+                       t[2]= c->t3*255.0;
+                       break;
+               default:
+                               break;
+       }
+       
+       /*find min/max tolerances*/
+       keymin[0]= key[0]-t[0];
+       keymin[1]= key[1]-t[1];
+       keymin[2]= key[2]-t[2];
+       keymax[0]= key[0]+t[0];
+       keymax[1]= key[1]+t[1];
+       keymax[2]= key[2]+t[2];
+       
+       /*tolerance*/
+       *tolerance= sqrt((t[0])*(t[0])+
+                                       (t[1])*(t[1])+
+                                       (t[2])*(t[2]));
+       
+       /* note, processor gets a keyvals array passed on as buffer constant */
+       composit2_pixel_processor(node, workbuf, workbuf, in[0]->vec, NULL, keyvals, do_diff_matte, CB_RGBA, CB_VAL);
+       
+       /*convert back to RGB colorspace*/
+       switch(node->custom1) {
+               case 1: /*RGB*/
+                       composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_copy_rgba, CB_RGBA);
+                       break;
+               case 2: /*HSV*/
+                       composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_hsva_to_rgba, CB_RGBA);
+                       break;
+               case 3: /*YUV*/
+                       composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA);
+                       break;
+               case 4: /*YCC*/
+                       composit1_pixel_processor(node, workbuf, workbuf, in[1]->vec, do_ycca_to_rgba, CB_RGBA);
+                       break;
+               default:
+                       break;
+       }
+       
+       out[0]->data=workbuf;
+       if(out[1]->hasoutput)
+               out[1]->data=valbuf_from_rgbabuf(workbuf, CHAN_A);
+       generate_preview(node, workbuf);
+
+       if(inbuf!=in[0]->data)
+               free_compbuf(inbuf);
+}
+
+static int node_composit_buts_diff_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      short sx= (butr->xmax-butr->xmin)/4;
+      short dx= (butr->xmax-butr->xmin)/3;
+      NodeChroma *c= node->storage;
+
+      uiBlockBeginAlign(block);
+      /*color space selectors*/
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"RGB",
+         butr->xmin,butr->ymin+60,sx,20,
+         &node->custom1,1,1, 0, 0, "RGB Color Space");
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"HSV",
+         butr->xmin+sx,butr->ymin+60,sx,20,
+         &node->custom1,1,2, 0, 0, "HSV Color Space");
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YUV",
+         butr->xmin+2*sx,butr->ymin+60,sx,20,
+         &node->custom1,1,3, 0, 0, "YUV Color Space");
+      uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YCC",
+         butr->xmin+3*sx,butr->ymin+60,sx,20,
+         &node->custom1,1,4, 0, 0, "YCbCr Color Space");
+      /*channel tolorences*/
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
+         butr->xmin, butr->ymin+40, dx, 20,
+         &c->t1, 0.0f, 1.0f, 100, 0, "Channel 1 Tolerance");
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
+         butr->xmin+dx, butr->ymin+40, dx, 20,
+         &c->t2, 0.0f, 1.0f, 100, 0, "Channel 2 Tolorence");
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
+         butr->xmin+2*dx, butr->ymin+40, dx, 20,
+         &c->t3, 0.0f, 1.0f, 100, 0, "Channel 3 Tolorence");
+      /*falloff parameters*/
+      /*
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff Size ",
+      butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
+      &c->fsize, 0.0f, 1.0f, 100, 0, "");
+      */
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff: ",
+         butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
+         &c->fstrength, 0.0f, 1.0f, 100, 0, "");
+   }
+   return 80;
+}
+
+static void node_composit_init_diff_matte(bNode *node)
+{
+   NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+   node->storage= c;
+   c->t1= 0.01f;
+   c->t2= 0.01f;
+   c->t3= 0.01f;
+   c->fsize= 0.0f;
+   c->fstrength= 0.0f;
+   node->custom1= 1; /* RGB */
+}
+
+bNodeType cmp_node_diff_matte={
+       /* type code   */       CMP_NODE_DIFF_MATTE,
+       /* name        */       "Difference Key",
+       /* width+range */       200, 80, 250,
+       /* class+opts  */       NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
+       /* input sock  */       cmp_node_diff_matte_in,
+       /* output sock */       cmp_node_diff_matte_out,
+       /* storage     */       "NodeChroma",
+       /* execfunc    */       node_composit_exec_diff_matte,
+   /* butfunc     */       node_composit_buts_diff_matte,
+                           node_composit_init_diff_matte
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_dilate.c b/source/blender/nodes/intern/CMP_nodes/CMP_dilate.c
new file mode 100644 (file)
index 0000000..8abf5ad
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** Dilate/Erode ******************** */
+
+static bNodeSocketType cmp_node_dilateerode_in[]= {
+       {       SOCK_VALUE, 1, "Mask",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_dilateerode_out[]= {
+       {       SOCK_VALUE, 0, "Mask",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void morpho_dilate(CompBuf *cbuf)
+{
+       int x, y;
+       float *p, *rectf = cbuf->rect;
+       
+       for (y=0; y < cbuf->y; y++) {
+               for (x=0; x < cbuf->x-1; x++) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MAX2(*p, *(p + 1));
+               }
+       }
+
+       for (y=0; y < cbuf->y; y++) {
+               for (x=cbuf->x-1; x >= 1; x--) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MAX2(*p, *(p - 1));
+               }
+       }
+
+       for (x=0; x < cbuf->x; x++) {
+               for (y=0; y < cbuf->y-1; y++) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MAX2(*p, *(p + cbuf->x));
+               }
+       }
+
+       for (x=0; x < cbuf->x; x++) {
+               for (y=cbuf->y-1; y >= 1; y--) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MAX2(*p, *(p - cbuf->x));
+               }
+       }
+}
+
+static void morpho_erode(CompBuf *cbuf)
+{
+       int x, y;
+       float *p, *rectf = cbuf->rect;
+       
+       for (y=0; y < cbuf->y; y++) {
+               for (x=0; x < cbuf->x-1; x++) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MIN2(*p, *(p + 1));
+               }
+       }
+
+       for (y=0; y < cbuf->y; y++) {
+               for (x=cbuf->x-1; x >= 1; x--) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MIN2(*p, *(p - 1));
+               }
+       }
+
+       for (x=0; x < cbuf->x; x++) {
+               for (y=0; y < cbuf->y-1; y++) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MIN2(*p, *(p + cbuf->x));
+               }
+       }
+
+       for (x=0; x < cbuf->x; x++) {
+               for (y=cbuf->y-1; y >= 1; y--) {
+                       p = rectf + cbuf->x*y + x;
+                       *p = MIN2(*p, *(p - cbuf->x));
+               }
+       }
+       
+}
+
+static void node_composit_exec_dilateerode(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order in: mask */
+       /* stack order out: mask */
+       if(out[0]->hasoutput==0) 
+               return;
+       
+       /* input no image? then only color operation */
+       if(in[0]->data==NULL) {
+               out[0]->vec[0] = out[0]->vec[1] = out[0]->vec[2] = 0.0f;
+               out[0]->vec[3] = 0.0f;
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_VAL);
+               CompBuf *stackbuf= dupalloc_compbuf(cbuf);
+               short i;
+               
+               if (node->custom2 > 0) { // positive, dilate
+                       for (i = 0; i < node->custom2; i++)
+                               morpho_dilate(stackbuf);
+               } else if (node->custom2 < 0) { // negative, erode
+                       for (i = 0; i > node->custom2; i--)
+                               morpho_erode(stackbuf);
+               }
+               
+               if(cbuf!=in[0]->data)
+                       free_compbuf(cbuf);
+               
+               out[0]->data= stackbuf;
+       }
+}
+
+static int node_composit_buts_dilateerode(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Distance:",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
+         &node->custom2, -100, 100, 0, 0, "Distance to grow/shrink (number of iterations)");
+   }
+   return 20;
+}
+
+bNodeType cmp_node_dilateerode= {
+       /* type code   */       CMP_NODE_DILATEERODE,
+       /* name        */       "Dilate/Erode",
+       /* width+range */       130, 100, 320,
+       /* class+opts  */       NODE_CLASS_OP_FILTER, NODE_OPTIONS,
+       /* input sock  */       cmp_node_dilateerode_in,
+       /* output sock */       cmp_node_dilateerode_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_dilateerode,
+   /* butfunc     */ node_composit_buts_dilateerode
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_displace.c b/source/blender/nodes/intern/CMP_nodes/CMP_displace.c
new file mode 100644 (file)
index 0000000..371f978
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** Displace  ******************** */
+
+static bNodeSocketType cmp_node_displace_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VECTOR, 1, "Vector",                       1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "X Scale",                               0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
+       {       SOCK_VALUE, 1, "Y Scale",                               0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_displace_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *veccol, float *xscale, float *yscale)
+{
+       ImBuf *ibuf;
+       int x, y, sx, sy;
+       float dx=0.0, dy=0.0;
+       float dspx, dspy;
+       float uv[2];
+
+       float *out= stackbuf->rect, *vec=vecbuf->rect, *in= cbuf->rect;
+       float *vp, *vpnext, *vpprev;
+       
+       int row = 3*vecbuf->x;
+       
+       /* ibuf needed for sampling */
+       ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
+       ibuf->rect_float= cbuf->rect;
+       
+       vec = vecbuf->rect;
+       
+       sx= stackbuf->x;
+       sy= stackbuf->y;
+       
+       for(y=0; y<sy; y++) {
+               for(x= 0; x< sx; x++, out+=4, in+=4, vec+=3) {
+                       
+                       /* the x-xrad stuff is a bit weird, but i seem to need it otherwise 
+                        * my returned pixels are offset weirdly */
+                       vp = compbuf_get_pixel(vecbuf, veccol, x-vecbuf->xrad, y-vecbuf->yrad, vecbuf->xrad, vecbuf->yrad);
+                       
+                       /* find the new displaced co-ords, also correcting for translate offset */
+                       dspx = x - (*xscale * vp[0]);
+                       dspy = y - (*yscale * vp[1]);
+
+                       /* convert image space to 0.0-1.0 UV space for sampling, correcting for translate offset */
+                       uv[0] = dspx / (float)sx;
+                       uv[1] = dspy / (float)sy;
+                       
+                       if(x>0 && x< vecbuf->x-1 && y>0 && y< vecbuf->y-1)  {
+                               vpnext = vp+row;
+                               vpprev = vp-row;
+                       
+                               /* adaptive sampling, X channel */
+                               dx= 0.5f*(fabs(vp[0]-vp[-3]) + fabs(vp[0]-vp[3]));
+                               
+                               dx+= 0.25f*(fabs(vp[0]-vpprev[-3]) + fabs(vp[0]-vpnext[-3]));
+                               dx+= 0.25f*(fabs(vp[0]-vpprev[+3]) + fabs(vp[0]-vpnext[+3]));
+                               
+                               /* adaptive sampling, Y channel */
+                               dy= 0.5f*(fabs(vp[1]-vp[-row+1]) + fabs(vp[1]-vp[row+1]));
+                                                
+                               dy+= 0.25f*(fabs(vp[1]-vpprev[+1-3]) + fabs(vp[1]-vpnext[+1-3]));
+                               dy+= 0.25f*(fabs(vp[1]-vpprev[+1+3]) + fabs(vp[1]-vpnext[+1+3]));
+                               
+                               /* scaled down to prevent blurriness */
+                               /* 8: magic number, provides a good level of sharpness without getting too aliased */
+                               dx /= 8;
+                               dy /= 8;
+                       }
+
+                       /* should use mipmap */
+                       if(dx > 0.006f) dx= 0.006f;
+                       if(dy > 0.006f) dy= 0.006f;
+                       if ((vp[0]> 0.0) && (dx < 0.004)) dx = 0.004;
+                       if ((vp[1]> 0.0) && (dy < 0.004)) dy = 0.004;
+                       
+
+                       ibuf_sample(ibuf, uv[0], uv[1], dx, dy, out);
+               }
+       }
+
+       IMB_freeImBuf(ibuf);    
+}
+
+
+static void node_composit_exec_displace(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(out[0]->hasoutput==0)
+               return;
+       
+       if(in[0]->data && in[1]->data) {
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *vecbuf= in[1]->data;
+               CompBuf *stackbuf;
+               
+               cbuf= typecheck_compbuf(cbuf, CB_RGBA);
+               vecbuf= typecheck_compbuf(vecbuf, CB_VEC3);
+               stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+
+               do_displace(stackbuf, cbuf, vecbuf, in[1]->vec, in[2]->vec, in[3]->vec);
+               
+               out[0]->data= stackbuf;
+               
+               
+               if(cbuf!=in[0]->data)
+                       free_compbuf(cbuf);
+               if(vecbuf!=in[1]->data)
+                       free_compbuf(vecbuf);
+       }
+}
+
+bNodeType cmp_node_displace= {
+       /* type code   */       CMP_NODE_DISPLACE,
+       /* name        */       "Displace",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS,
+       /* input sock  */       cmp_node_displace_in,
+       /* output sock */       cmp_node_displace_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_displace,
+   /* butfunc     */ NULL
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_filter.c b/source/blender/nodes/intern/CMP_nodes/CMP_filter.c
new file mode 100644 (file)
index 0000000..d5fb6c3
--- /dev/null
@@ -0,0 +1,243 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** FILTER  ******************** */
+static bNodeSocketType cmp_node_filter_in[]= {
+       {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_filter_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
+{
+       float *row1, *row2, *row3;
+       float *fp, f1, f2, mfac= 1.0f-fac;
+       int rowlen, x, y, c, pix= in->type;
+       
+       rowlen= in->x;
+       
+       for(y=0; y<in->y; y++) {
+               /* setup rows */
+               if(y==0) row1= in->rect;
+               else row1= in->rect + pix*(y-1)*rowlen;
+               
+               row2= in->rect + y*pix*rowlen;
+               
+               if(y==in->y-1) row3= row2;
+               else row3= row2 + pix*rowlen;
+               
+               fp= out->rect + pix*y*rowlen;
+               
+               if(pix==CB_RGBA) {
+                       QUATCOPY(fp, row2);
+                       fp+= pix;
+                       
+                       for(x=2; x<rowlen; x++) {
+                               for(c=0; c<3; c++) {
+                                       f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8];
+                                       f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8];
+                                       fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
+                                       fp++; row1++; row2++; row3++;
+                               }
+                               fp[0]= row2[4];
+                               /* no alpha... will clear it completely */
+                               fp++; row1++; row2++; row3++;
+                       }
+                       QUATCOPY(fp, row2+4);
+               }
+               else if(pix==CB_VAL) {
+                       for(x=2; x<rowlen; x++) {
+                               f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2];
+                               f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2];
+                               fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
+                               fp++; row1++; row2++; row3++;
+                       }
+               }
+       }
+}
+
+static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
+{
+       float *row1, *row2, *row3;
+       float *fp, mfac= 1.0f-fac;
+       int rowlen, x, y, c;
+       int pixlen= in->type;
+       
+       rowlen= in->x;
+       
+       for(y=0; y<in->y; y++) {
+               /* setup rows */
+               if(y==0) row1= in->rect;
+               else row1= in->rect + pixlen*(y-1)*rowlen;
+               
+               row2= in->rect + y*pixlen*rowlen;
+               
+               if(y==in->y-1) row3= row2;
+               else row3= row2 + pixlen*rowlen;
+               
+               fp= out->rect + pixlen*(y)*rowlen;
+               
+               if(pixlen==1) {
+                       fp[0]= row2[0];
+                       fp+= 1;
+                       
+                       for(x=2; x<rowlen; x++) {
+                               fp[0]= mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]);
+                               fp++; row1++; row2++; row3++;
+                       }
+                       fp[0]= row2[1];
+               }
+               else if(pixlen==2) {
+                       fp[0]= row2[0];
+                       fp[1]= row2[1];
+                       fp+= 2;
+                       
+                       for(x=2; x<rowlen; x++) {
+                               for(c=0; c<2; c++) {
+                                       fp[0]= mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]);
+                                       fp++; row1++; row2++; row3++;
+                               }
+                       }
+                       fp[0]= row2[2];
+                       fp[1]= row2[3];
+               }
+               else if(pixlen==3) {
+                       VECCOPY(fp, row2);
+                       fp+= 3;
+                       
+                       for(x=2; x<rowlen; x++) {
+                               for(c=0; c<3; c++) {
+                                       fp[0]= mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]);
+                                       fp++; row1++; row2++; row3++;
+                               }
+                       }
+                       VECCOPY(fp, row2+3);
+               }
+               else {
+                       QUATCOPY(fp, row2);
+                       fp+= 4;
+                       
+                       for(x=2; x<rowlen; x++) {
+                               for(c=0; c<4; c++) {
+                                       fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]);
+                                       fp++; row1++; row2++; row3++;
+                               }
+                       }
+                       QUATCOPY(fp, row2+4);
+               }
+       }
+}
+
+
+static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       static float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
+       float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
+       float laplace[9]= {-1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f, 1.0f, -1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f};
+       float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
+       float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
+       float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
+       float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
+       
+       if(out[0]->hasoutput==0) return;
+       
+       /* stack order in: Image */
+       /* stack order out: Image */
+       
+       if(in[1]->data) {
+               /* make output size of first available input image */
+               CompBuf *cbuf= in[1]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */
+               
+               /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
+               stackbuf->xof= cbuf->xof;
+               stackbuf->yof= cbuf->yof;
+               
+               switch(node->custom1) {
+                       case CMP_FILT_SOFT:
+                               do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
+                               break;
+                       case CMP_FILT_SHARP:
+                               do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
+                               break;
+                       case CMP_FILT_LAPLACE:
+                               do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
+                               break;
+                       case CMP_FILT_SOBEL:
+                               do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
+                               break;
+                       case CMP_FILT_PREWITT:
+                               do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
+                               break;
+                       case CMP_FILT_KIRSCH:
+                               do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
+                               break;
+                       case CMP_FILT_SHADOW:
+                               do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
+                               break;
+               }
+                       
+               out[0]->data= stackbuf;
+       }
+}
+
+static int node_composit_buts_filter(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      uiBut *bt;
+
+      /* blend type */
+      bt=uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "Soften %x0|Sharpen %x1|Laplace %x2|Sobel %x3|Prewitt %x4|Kirsch %x5|Shadow %x6",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
+         &node->custom1, 0, 0, 0, 0, "");
+      uiButSetFunc(bt, node_but_title_cb, node, bt);
+   }
+   return 20;
+}
+
+bNodeType cmp_node_filter= {
+       /* type code   */       CMP_NODE_FILTER,
+       /* name        */       "Filter",
+       /* width+range */       80, 40, 120,
+       /* class+opts  */       NODE_CLASS_OP_FILTER, NODE_OPTIONS,
+       /* input sock  */       cmp_node_filter_in,
+       /* output sock */       cmp_node_filter_out,
+       /* storage     */       "", 
+       /* execfunc    */       node_composit_exec_filter,
+   /* butfunc     */ node_composit_buts_filter
+       
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_flip.c b/source/blender/nodes/intern/CMP_nodes/CMP_flip.c
new file mode 100644 (file)
index 0000000..b80983d
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** Flip  ******************** */
+static bNodeSocketType cmp_node_flip_in[]= {
+       {       SOCK_RGBA, 1, "Image",              0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketType cmp_node_flip_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_flip(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(in[0]->data) {
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1);      /* note, this returns zero'd image */
+               int i, src_pix, src_width, src_height, srcydelt, outydelt, x, y;
+               float *srcfp, *outfp;
+               
+               src_pix= cbuf->type;
+               src_width= cbuf->x;
+               src_height= cbuf->y;
+               srcfp= cbuf->rect;
+               outfp= stackbuf->rect;
+               srcydelt= src_width*src_pix;
+               outydelt= srcydelt;
+               
+               if(node->custom1) {             /*set up output pointer for y flip*/
+                       outfp+= (src_height-1)*outydelt;
+                       outydelt= -outydelt;
+               }
+
+               for(y=0; y<src_height; y++) {
+                       if(node->custom1 == 1) {        /* no x flip so just copy line*/
+                               memcpy(outfp, srcfp, sizeof(float) * src_pix * src_width);
+                               srcfp+=srcydelt;
+                       }
+                       else {
+                               outfp += (src_width-1)*src_pix;
+                               for(x=0; x<src_width; x++) {
+                                       for(i=0; i<src_pix; i++) {
+                                               outfp[i]= srcfp[i];
+                                       }
+                                       outfp -= src_pix;
+                                       srcfp += src_pix;
+                               }
+                               outfp += src_pix;
+                       }
+                       outfp += outydelt;
+               }
+
+               out[0]->data= stackbuf;
+
+       }
+}
+
+static int node_composit_buts_flip(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
+{
+   if(block) {
+      uiBut *bt;
+
+      /* flip x\y */
+      bt=uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "Flip X %x0|Flip Y %x1|Flip X & Y %x2",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
+         &node->custom1, 0, 0, 0, 0, "");
+      uiButSetFunc(bt, node_but_title_cb, node, bt);
+   }
+   return 20;  
+}
+
+bNodeType cmp_node_flip= {
+       /* type code   */       CMP_NODE_FLIP,
+       /* name        */       "Flip",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS,
+       /* input sock  */       cmp_node_flip_in,
+       /* output sock */       cmp_node_flip_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_flip,
+   /* butfunc     */ node_composit_buts_flip
+};
\ No newline at end of file
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c b/source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c
new file mode 100644 (file)
index 0000000..f833b13
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** Hue Saturation ******************** */
+static bNodeSocketType cmp_node_hue_sat_in[]= {
+       {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_hue_sat_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_hue_sat_fac(bNode *node, float *out, float *in, float *fac)
+{
+       NodeHueSat *nhs= node->storage;
+       
+       if(*fac!=0.0f && (nhs->hue!=0.5f || nhs->sat!=1.0 || nhs->val!=1.0)) {
+               float col[3], hsv[3], mfac= 1.0f - *fac;
+               
+               rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
+               hsv[0]+= (nhs->hue - 0.5f);
+               if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
+               hsv[1]*= nhs->sat;
+               if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
+               hsv[2]*= nhs->val;
+               if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0;
+               hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
+               
+               out[0]= mfac*in[0] + *fac*col[0];
+               out[1]= mfac*in[1] + *fac*col[1];
+               out[2]= mfac*in[2] + *fac*col[2];
+               out[3]= in[3];
+       }
+       else {
+               QUATCOPY(out, in);
+       }
+}
+
+static void node_composit_exec_hue_sat(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order in: Fac, Image */
+       /* stack order out: Image */
+       if(out[0]->hasoutput==0) return;
+       
+       /* input no image? then only color operation */
+       if(in[1]->data==NULL) {
+               do_hue_sat_fac(node, out[0]->vec, in[1]->vec, in[0]->vec);
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= dupalloc_compbuf(in[1]->data);
+               CompBuf *stackbuf=typecheck_compbuf(cbuf,CB_RGBA);
+               
+               composit2_pixel_processor(node, stackbuf, stackbuf, in[1]->vec, in[0]->data, in[0]->vec, do_hue_sat_fac, CB_RGBA, CB_VAL);
+
+               out[0]->data= stackbuf;
+
+               /* get rid of intermediary cbuf if it's extra */                
+               if(stackbuf!=cbuf)
+                       free_compbuf(cbuf);
+       }
+}
+
+static int node_composit_buts_hue_sat(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      NodeHueSat *nhs= node->storage;
+
+      uiBlockBeginAlign(block);
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Hue: ",
+         butr->xmin, butr->ymin+40.0f, butr->xmax-butr->xmin, 20, 
+         &nhs->hue, 0.0f, 1.0f, 100, 0, "");
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Sat: ",
+         butr->xmin, butr->ymin+20.0f, butr->xmax-butr->xmin, 20, 
+         &nhs->sat, 0.0f, 2.0f, 100, 0, "");
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Val: ",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
+         &nhs->val, 0.0f, 2.0f, 100, 0, "");
+   }
+   return 60;
+}
+
+static void node_composit_init_hue_sat(bNode* node)
+{
+   NodeHueSat *nhs= MEM_callocN(sizeof(NodeHueSat), "node hue sat");
+   node->storage= nhs;
+   nhs->hue= 0.5f;
+   nhs->sat= 1.0f;
+   nhs->val= 1.0f;
+}
+
+bNodeType cmp_node_hue_sat= {
+       /* type code   */       CMP_NODE_HUE_SAT,
+       /* name        */       "Hue Saturation Value",
+       /* width+range */       150, 80, 250,
+       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_hue_sat_in,
+       /* output sock */       cmp_node_hue_sat_out,
+       /* storage     */       "NodeHueSat", 
+       /* execfunc    */       node_composit_exec_hue_sat,
+   /* butfunc     */ node_composit_buts_hue_sat,
+                     node_composit_init_hue_sat
+       
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c b/source/blender/nodes/intern/CMP_nodes/CMP_idMask.c
new file mode 100644 (file)
index 0000000..312b32a
--- /dev/null
@@ -0,0 +1,109 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** ID Mask  ******************** */
+
+static bNodeSocketType cmp_node_idmask_in[]= {
+       {       SOCK_VALUE, 1, "ID value",                      0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_idmask_out[]= {
+       {       SOCK_VALUE, 0, "Alpha",                 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+/* stackbuf should be zeroed */
+static void do_idmask(CompBuf *stackbuf, CompBuf *cbuf, float idnr)
+{
+       float *rect;
+       int x;
+       char *abuf= MEM_mapallocN(cbuf->x*cbuf->y, "anti ali buf");
+       
+       rect= cbuf->rect;
+       for(x= cbuf->x*cbuf->y - 1; x>=0; x--)
+               if(rect[x]==idnr)
+                       abuf[x]= 255;
+       
+       antialias_tagbuf(cbuf->x, cbuf->y, abuf);
+       
+       rect= stackbuf->rect;
+       for(x= cbuf->x*cbuf->y - 1; x>=0; x--)
+               if(abuf[x]>1)
+                       rect[x]= (1.0f/255.0f)*(float)abuf[x];
+       
+       MEM_freeN(abuf);
+}
+
+static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(out[0]->hasoutput==0)
+               return;
+       
+       if(in[0]->data) {
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf;
+               
+               if(cbuf->type!=CB_VAL)
+                       return;
+               
+               stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */;
+               
+               do_idmask(stackbuf, cbuf, (float)node->custom1);
+               
+               out[0]->data= stackbuf;
+       }
+}
+
+
+static int node_composit_buts_id_mask(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "ID:",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
+         &node->custom1, 0, 10000, 0, 0, "Pass Index number to convert to Alpha");
+   }
+   return 20;
+}
+
+bNodeType cmp_node_idmask= {
+       /* type code   */       CMP_NODE_ID_MASK,
+       /* name        */       "ID Mask",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_idmask_in,
+       /* output sock */       cmp_node_idmask_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_idmask,
+   /* butfunc     */ node_composit_buts_id_mask
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_image.c b/source/blender/nodes/intern/CMP_nodes/CMP_image.c
new file mode 100644 (file)
index 0000000..563643a
--- /dev/null
@@ -0,0 +1,639 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
+
+static bNodeSocketType cmp_node_rlayers_out[]= {
+       {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VECTOR, 0, "UV",           1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VECTOR, 0, "Speed",        1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "Color",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "Diffuse",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "Specular",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "Shadow",         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "AO",                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "Reflect",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "Refract",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 0, "Radio",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "IndexOB",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+
+/* note: this function is used for multilayer too, to ensure uniform 
+   handling with BKE_image_get_ibuf() */
+static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
+{
+       ImBuf *ibuf;
+       CompBuf *stackbuf;
+       int type;
+       
+       ibuf= BKE_image_get_ibuf(ima, iuser);
+       if(ibuf==NULL)
+               return NULL;
+       
+       if(ibuf->rect_float==NULL)
+               IMB_float_from_rect(ibuf);
+       
+       type= ibuf->channels;
+       
+       if(rd->scemode & R_COMP_CROP) {
+               stackbuf= get_cropped_compbuf(&rd->disprect, ibuf->rect_float, ibuf->x, ibuf->y, type);
+       }
+       else {
+               /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
+               stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, 0);
+               stackbuf->rect= ibuf->rect_float;
+       }
+       
+       return stackbuf;
+};
+
+static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
+{
+       ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
+       CompBuf *zbuf= NULL;
+       
+       if(ibuf && ibuf->zbuf_float) {
+               if(rd->scemode & R_COMP_CROP) {
+                       zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
+               }
+               else {
+                       zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
+                       zbuf->rect= ibuf->zbuf_float;
+               }
+       }
+       return zbuf;
+};
+
+/* check if layer is available, returns pass buffer */
+static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype)
+{
+       RenderPass *rpass;
+       short index;
+       
+       for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++)
+               if(rpass->passtype==passtype)
+                       break;
+       
+       if(rpass) {
+               CompBuf *cbuf;
+               
+               iuser->pass= index;
+               BKE_image_multilayer_index(ima->rr, iuser);
+               cbuf= node_composit_get_image(rd, ima, iuser);
+               
+               return cbuf;
+       }
+       return NULL;
+};
+
+void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser)
+{
+       if(out[RRES_OUT_Z]->hasoutput)
+               out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z);
+       if(out[RRES_OUT_VEC]->hasoutput)
+               out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR);
+       if(out[RRES_OUT_NORMAL]->hasoutput)
+               out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL);
+       if(out[RRES_OUT_UV]->hasoutput)
+               out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV);
+       
+       if(out[RRES_OUT_RGBA]->hasoutput)
+               out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA);
+       if(out[RRES_OUT_DIFF]->hasoutput)
+               out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE);
+       if(out[RRES_OUT_SPEC]->hasoutput)
+               out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC);
+       if(out[RRES_OUT_SHADOW]->hasoutput)
+               out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW);
+       if(out[RRES_OUT_AO]->hasoutput)
+               out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO);
+       if(out[RRES_OUT_REFLECT]->hasoutput)
+               out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT);
+       if(out[RRES_OUT_REFRACT]->hasoutput)
+               out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT);
+       if(out[RRES_OUT_RADIO]->hasoutput)
+               out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO);
+       if(out[RRES_OUT_INDEXOB]->hasoutput)
+               out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
+       
+};
+
+
+static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       
+       /* image assigned to output */
+       /* stack order input sockets: col, alpha */
+       if(node->id) {
+               RenderData *rd= data;
+               Image *ima= (Image *)node->id;
+               ImageUser *iuser= (ImageUser *)node->storage;
+               CompBuf *stackbuf= NULL;
+               
+               /* first set the right frame number in iuser */
+               BKE_image_user_calc_imanr(iuser, rd->cfra, 0);
+               
+               /* force a load, we assume iuser index will be set OK anyway */
+               if(ima->type==IMA_TYPE_MULTILAYER)
+                       BKE_image_get_ibuf(ima, iuser);
+               
+               if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
+                       RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
+                       
+                       if(rl) {
+                               out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED);
+                               
+                               /* go over all layers */
+                               outputs_multilayer_get(rd, rl, out, ima, iuser);
+                       }
+               }
+               else {
+                       stackbuf= node_composit_get_image(rd, ima, iuser);
+
+                       /* put image on stack */        
+                       out[0]->data= stackbuf;
+                       
+                       if(out[2]->hasoutput)
+                               out[2]->data= node_composit_get_zimage(node, rd);
+               }
+               
+               /* alpha and preview for both types */
+               if(stackbuf) {
+                       if(out[1]->hasoutput)
+                               out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
+
+                       generate_preview(node, stackbuf);
+               }
+       }       
+};
+
+static void node_browse_image_cb(void *ntree_v, void *node_v)
+{
+   bNodeTree *ntree= ntree_v;
+   bNode *node= node_v;
+
+   nodeSetActive(ntree, node);
+
+   if(node->menunr<1) return;
+   if(node->menunr==32767) {   /* code for Load New */
+      addqueue(curarea->win, UI_BUT_EVENT, B_NODE_LOADIMAGE);
+   }
+   else {
+      if(node->id) node->id->us--;
+      node->id= BLI_findlink(&G.main->image, node->menunr-1);
+      id_us_plus(node->id);
+
+      BLI_strncpy(node->name, node->id->name+2, 21);
+
+      NodeTagChanged(ntree, node); 
+      BKE_image_signal((Image *)node->id, node->storage, IMA_SIGNAL_USER_NEW_IMAGE);
+      addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr);
+   }
+   node->menunr= 0;
+};
+
+static void node_active_cb(void *ntree_v, void *node_v)
+{
+   nodeSetActive(ntree_v, node_v);
+};
+
+static void node_image_type_cb(void *node_v, void *unused)
+{
+
+   allqueue(REDRAWNODE, 1);
+};
+
+static char *node_image_type_pup(void)
+{
+   char *str= MEM_mallocN(256, "image type pup");
+   int a;
+
+   str[0]= 0;
+
+   a= sprintf(str, "Image Type %%t|");
+   a+= sprintf(str+a, "  Image %%x%d %%i%d|", IMA_SRC_FILE, ICON_IMAGE_DEHLT);
+   a+= sprintf(str+a, "  Movie %%x%d %%i%d|", IMA_SRC_MOVIE, ICON_SEQUENCE);
+   a+= sprintf(str+a, "  Sequence %%x%d %%i%d|", IMA_SRC_SEQUENCE, ICON_IMAGE_COL);
+   a+= sprintf(str+a, "  Generated %%x%d %%i%d", IMA_SRC_GENERATED, ICON_BLANK1);
+
+   return str;
+};
+
+/* copy from buttons_shading.c */
+static char *layer_menu(RenderResult *rr)
+{
+   RenderLayer *rl;
+   int len= 40 + 40*BLI_countlist(&rr->layers);
+   short a, nr;
+   char *str= MEM_callocN(len, "menu layers");
+
+   strcpy(str, "Layer %t");
+   a= strlen(str);
+   for(nr=0, rl= rr->layers.first; rl; rl= rl->next, nr++) {
+      a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
+   }
+
+   return str;
+};
+
+static void image_layer_cb(void *ima_v, void *iuser_v)
+{
+
+   ntreeCompositForceHidden(G.scene->nodetree);
+   BKE_image_multilayer_index(ima_v, iuser_v);
+   allqueue(REDRAWNODE, 0);
+};
+
+static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   ImageUser *iuser= node->storage;
+
+   if(block) {
+      uiBut *bt;
+      short dy= (short)butr->ymax-19;
+      char *strp;
+
+      uiBlockBeginAlign(block);
+      uiBlockSetCol(block, TH_BUT_SETTING2);
+
+      /* browse button */
+      IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
+      node->menunr= 0;
+      bt= uiDefButS(block, MENU, B_NOP, strp, 
+         butr->xmin, dy, 19, 19, 
+         &node->menunr, 0, 0, 0, 0, "Browses existing choices");
+      uiButSetFunc(bt, node_browse_image_cb, ntree, node);
+      if(strp) MEM_freeN(strp);
+
+      /* Add New button */
+      if(node->id==NULL) {
+         bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
+            butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, 
+            NULL, 0.0, 0.0, 0, 0, "Add new Image");
+         uiButSetFunc(bt, node_active_cb, ntree, node);
+         uiBlockSetCol(block, TH_AUTO);
+      }
+      else {
+         /* name button + type */
+         Image *ima= (Image *)node->id;
+         short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
+         short width= xmax - xmin - 45;
+         short icon= ICON_IMAGE_DEHLT;
+
+         if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE;
+         else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL;
+         else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1;
+
+         bt= uiDefBut(block, TEX, B_NOP, "IM:",
+            xmin+19, dy, width, 19, 
+            node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
+         uiButSetFunc(bt, node_ID_title_cb, node, NULL);
+
+         /* buffer type option */
+         strp= node_image_type_pup();
+         bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp,
+            xmax-26, dy, 26, 19, 
+            &ima->source, 0.0, 19.0, 0, 0, "Image type");
+         uiButSetFunc(bt, node_image_type_cb, node, ima);
+         MEM_freeN(strp);
+
+         if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) {
+            width= (xmax-xmin)/2;
+
+            dy-= 19;
+            uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Frs:",
+               xmin, dy, width, 19, 
+               &iuser->frames, 0.0, 10000.0, 0, 0, "Amount of images used in animation");
+            uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra:",
+               xmin+width, dy, width, 19, 
+               &iuser->sfra, 1.0, 10000.0, 0, 0, "Start frame of animation");
+            dy-= 19;
+            uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Offs:",
+               xmin, dy, width, 19, 
+               &iuser->offset, 0.0, 10000.0, 0, 0, "Offsets the number of the frame to use in the animation");
+            uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Cycl",
+               xmin+width, dy, width-20, 19, 
+               &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic");
+            uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC+node->nr, ICON_AUTO,
+               xmax-20, dy, 20, 19, 
+               &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes");
+         }
+         if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
+            RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
+            if(rl) {
+               width= (xmax-xmin);
+               dy-= 19;
+               strp= layer_menu(ima->rr);
+               bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp,
+                  xmin, dy, width, 19, 
+                  &iuser->layer, 0.0, 10000.0, 0, 0, "Layer");
+               uiButSetFunc(bt, image_layer_cb, ima, node->storage);
+               MEM_freeN(strp);
+            }
+         }
+      }
+
+   }   
+   if(node->id) {
+      Image *ima= (Image *)node->id;
+      int retval= 19;
+
+      /* for each draw we test for anim refresh event */
+      if(iuser->flag & IMA_ANIM_REFRESHED) {
+         iuser->flag &= ~IMA_ANIM_REFRESHED;
+         addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr);
+      }
+
+      if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) )
+         retval+= 38;
+      if( ima->type==IMA_TYPE_MULTILAYER)
+         retval+= 19;
+      return retval;
+   }
+   else
+      return 19;
+};
+
+static void node_composit_init_image(bNode* node)
+{
+   ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
+   node->storage= iuser;
+   iuser->sfra= 1;
+   iuser->fie_ima= 2;
+   iuser->ok= 1;
+}
+
+bNodeType cmp_node_image= {
+   /* type code   */   CMP_NODE_IMAGE,
+   /* name        */   "Image",
+   /* width+range */   120, 80, 300,
+   /* class+opts  */   NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
+   /* input sock  */   NULL,
+   /* output sock */   cmp_node_rlayers_out,
+   /* storage     */   "ImageUser",
+   /* execfunc    */   node_composit_exec_image,
+   /* butfunc     */ node_composit_buts_image,
+                     node_composit_init_image
+};
+
+/* **************** RENDER RESULT ******************** */
+
+static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
+{
+   float *fp= RE_RenderLayerGetPass(rl, passcode);
+   if(fp) {
+      CompBuf *buf;
+      int buftype= CB_VEC3;
+
+      if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB))
+         buftype= CB_VAL;
+      else if(passcode==SCE_PASS_VECTOR)
+         buftype= CB_VEC4;
+      else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
+         buftype= CB_RGBA;
+
+      if(rd->scemode & R_COMP_CROP)
+         buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
+      else {
+         buf= alloc_compbuf(rectx, recty, buftype, 0);
+         buf->rect= fp;
+      }
+      return buf;
+   }
+   return NULL;
+};
+
+void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
+{
+   if(out[RRES_OUT_Z]->hasoutput)
+      out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
+   if(out[RRES_OUT_VEC]->hasoutput)
+      out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
+   if(out[RRES_OUT_NORMAL]->hasoutput)
+      out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
+   if(out[RRES_OUT_UV]->hasoutput)
+      out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
+
+   if(out[RRES_OUT_RGBA]->hasoutput)
+      out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
+   if(out[RRES_OUT_DIFF]->hasoutput)
+      out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
+   if(out[RRES_OUT_SPEC]->hasoutput)
+      out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
+   if(out[RRES_OUT_SHADOW]->hasoutput)
+      out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
+   if(out[RRES_OUT_AO]->hasoutput)
+      out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
+   if(out[RRES_OUT_REFLECT]->hasoutput)
+      out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
+   if(out[RRES_OUT_REFRACT]->hasoutput)
+      out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
+   if(out[RRES_OUT_RADIO]->hasoutput)
+      out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO);
+   if(out[RRES_OUT_INDEXOB]->hasoutput)
+      out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
+
+};
+
+static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+   Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */
+   RenderData *rd= data;
+   RenderResult *rr;
+
+   rr= RE_GetResult(RE_GetRender(sce->id.name));
+
+   if(rr) {
+      SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
+      if(srl) {
+         RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
+         if(rl && rl->rectf) {
+            CompBuf *stackbuf;
+
+            /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
+            if(rd->scemode & R_COMP_CROP)
+               stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
+            else {
+               stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
+               stackbuf->rect= rl->rectf;
+            }
+            if(stackbuf==NULL) {
+               printf("Error; Preview Panel in UV Window returns zero sized image\n");
+            }
+            else {
+               stackbuf->xof= rr->xof;
+               stackbuf->yof= rr->yof;
+
+               /* put on stack */      
+               out[RRES_OUT_IMAGE]->data= stackbuf;
+
+               if(out[RRES_OUT_ALPHA]->hasoutput)
+                  out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
+
+               node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
+
+               generate_preview(node, stackbuf);
+            }
+         }
+      }
+   }   
+};
+
+/* if we use render layers from other scene, we make a nice title */
+static void set_render_layers_title(void *node_v, void *unused)
+{
+   bNode *node= node_v;
+   Scene *sce;
+   SceneRenderLayer *srl;
+   char str[64];
+
+   if(node->id) {
+      BLI_strncpy(str, node->id->name+2, 21);
+      strcat(str, "|");
+      sce= (Scene *)node->id;
+   }
+   else {
+      str[0]= 0;
+      sce= G.scene;
+   }
+   srl= BLI_findlink(&sce->r.layers, node->custom1);
+   if(srl==NULL) {
+      node->custom1= 0;
+      srl= sce->r.layers.first;
+   }
+
+   strcat(str, srl->name);
+   BLI_strncpy(node->name, str, 32);
+};
+
+static char *scene_layer_menu(Scene *sce)
+{
+   SceneRenderLayer *srl;
+   int len= 40 + 40*BLI_countlist(&sce->r.layers);
+   short a, nr;
+   char *str= MEM_callocN(len, "menu layers");
+
+   strcpy(str, "Active Layer %t");
+   a= strlen(str);
+   for(nr=0, srl= sce->r.layers.first; srl; srl= srl->next, nr++) {
+      a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
+   }
+
+   return str;
+};
+
+static void node_browse_scene_cb(void *ntree_v, void *node_v)
+{
+   bNodeTree *ntree= ntree_v;
+   bNode *node= node_v;
+   Scene *sce;
+
+   if(node->menunr<1) return;
+
+   if(node->id) {
+      node->id->us--;
+      node->id= NULL;
+   }
+   sce= BLI_findlink(&G.main->scene, node->menunr-1);
+   if(sce!=G.scene) {
+      node->id= &sce->id;
+      id_us_plus(node->id);
+   }
+
+   set_render_layers_title(node, NULL);
+   nodeSetActive(ntree, node);
+
+   allqueue(REDRAWBUTSSHADING, 0);
+   allqueue(REDRAWNODE, 0);
+   NodeTagChanged(ntree, node); 
+
+   node->menunr= 0;
+};
+
+static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      uiBut *bt;
+      char *strp;
+
+      /* browse button scene */
+      uiBlockBeginAlign(block);
+      IDnames_to_pupstring(&strp, NULL, "", &(G.main->scene), NULL, NULL);
+      node->menunr= 0;
+      bt= uiDefButS(block, MENU, B_NOP, strp, 
+         butr->xmin, butr->ymin, 20, 19, 
+         &node->menunr, 0, 0, 0, 0, "Browse Scene to use RenderLayer from");
+      uiButSetFunc(bt, node_browse_scene_cb, ntree, node);
+      if(strp) MEM_freeN(strp);
+
+      /* browse button layer */
+      strp= scene_layer_menu(node->id?(Scene *)node->id:G.scene);
+      if(node->id)
+         bt= uiDefIconTextButS(block, MENU, B_NODE_EXEC+node->nr, ICON_SCENE_DEHLT, strp, 
+         butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
+         &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
+      else
+         bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp, 
+         butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
+         &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
+      uiButSetFunc(bt, set_render_layers_title, node, NULL);
+      MEM_freeN(strp);
+
+      /* re-render */
+      /* uses custom2, not the best implementation of the world... but we need it to work now :) */
+      bt= uiDefIconButS(block, TOG, B_NODE_EXEC+node->nr, ICON_SCENE, 
+         butr->xmax-20, butr->ymin, 20, 19, 
+         &node->custom2, 0, 0, 0, 0, "Re-render this Layer");
+
+   }
+   return 19;
+};
+
+
+bNodeType cmp_node_rlayers= {
+   /* type code   */   CMP_NODE_R_LAYERS,
+   /* name        */   "Render Layers",
+   /* width+range */   150, 100, 300,
+   /* class+opts  */   NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
+   /* input sock  */   NULL,
+   /* output sock */   cmp_node_rlayers_out,
+   /* storage     */   "",
+   /* execfunc    */   node_composit_exec_rlayers,
+   /* butfunc     */ node_composit_buts_renderlayers,
+                     NULL
+
+};
\ No newline at end of file
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c
new file mode 100644 (file)
index 0000000..f010cbf
--- /dev/null
@@ -0,0 +1,140 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* ******************* Luma Matte Node ********************************* */
+static bNodeSocketType cmp_node_luma_matte_in[]={
+       {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static bNodeSocketType cmp_node_luma_matte_out[]={
+       {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {SOCK_VALUE,0,"Matte",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {-1,0,""}
+};
+
+static void do_luma_matte(bNode *node, float *out, float *in)
+{
+       NodeChroma *c=(NodeChroma *)node->storage;
+       float alpha;
+
+       alpha=0.0;
+
+       /* test range*/
+       if(in[0]>c->t1) {
+               alpha=1.0;
+       }
+       else if(in[1]<c->t2){
+               alpha=0.0;
+       }
+       else {/*blend */
+               alpha=(in[0]-c->t2)/(c->t1-c->t2);
+       }
+       
+       /* don't make something that was more transparent less transparent */
+       if (alpha<in[3]) {
+               out[3]=alpha;
+       }
+       else {
+               out[3]=in[3];
+       }
+
+}
+
+static void node_composit_exec_luma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       CompBuf *cbuf;
+       CompBuf *outbuf;
+       
+       if(in[0]->hasinput==0)  return;
+       if(in[0]->data==NULL) return;
+       if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
+       
+       cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
+       
+       outbuf=dupalloc_compbuf(cbuf);
+
+       composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA);
+       composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_luma_matte, CB_RGBA);
+       composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA);
+       
+       generate_preview(node, outbuf);
+       out[0]->data=outbuf;
+       if (out[1]->hasoutput)
+               out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A);
+       if(cbuf!=in[0]->data)
+               free_compbuf(cbuf);
+}
+
+static int node_composit_buts_luma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      NodeChroma *c=node->storage;
+
+      /*tolerance sliders */
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "High ", 
+         butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
+         &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque");
+      uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Low ", 
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
+         &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed");
+      uiBlockEndAlign(block);
+
+      /*keep t2 (low) less than t1 (high) */
+      if(c->t2 > c->t1) {
+         c->t2=c->t1;
+      }
+   }
+   return 40;
+}
+
+static void node_composit_init_luma_matte(bNode *node)
+{
+   NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
+   node->storage=c;
+   c->t1= 0.0f;
+   c->t2= 0.0f;
+};
+
+bNodeType cmp_node_luma_matte={
+       /* type code   */       CMP_NODE_LUMA_MATTE,
+       /* name        */       "Luminance Key",
+       /* width+range */       200, 80, 250,
+       /* class+opts  */       NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS,
+       /* input sock  */       cmp_node_luma_matte_in,
+       /* output sock */       cmp_node_luma_matte_out,
+       /* storage     */       "NodeChroma",
+       /* execfunc    */       node_composit_exec_luma_matte,
+   /* butfunc     */       node_composit_buts_luma_matte,
+                           node_composit_init_luma_matte
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_mapUV.c b/source/blender/nodes/intern/CMP_nodes/CMP_mapUV.c
new file mode 100644 (file)
index 0000000..a0b35ab
--- /dev/null
@@ -0,0 +1,154 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** Map UV  ******************** */
+
+static bNodeSocketType cmp_node_mapuv_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VECTOR, 1, "UV",                   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_mapuv_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+/* foreach UV, use these values to read in cbuf and write to stackbuf */
+/* stackbuf should be zeroed */
+static void do_mapuv(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *uvbuf, float threshold)
+{
+       ImBuf *ibuf;
+       float *out= stackbuf->rect, *uv, *uvnext, *uvprev;
+       float dx, dy, alpha;
+       int x, y, sx, sy, row= 3*stackbuf->x;
+       
+       /* ibuf needed for sampling */
+       ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
+       ibuf->rect_float= cbuf->rect;
+       
+       /* vars for efficient looping */
+       uv= uvbuf->rect;
+       uvnext= uv+row;
+       uvprev= uv-row;
+       sx= stackbuf->x;
+       sy= stackbuf->y;
+       
+       for(y=0; y<sy; y++) {
+               for(x=0; x<sx; x++, out+=4, uv+=3, uvnext+=3, uvprev+=3) {
+                       if(x>0 && x<sx-1 && y>0 && y<sy-1) {
+                               if(uv[2]!=0.0f) {
+                                       
+                                       /* adaptive sampling, red (U) channel */
+                                       dx= 0.5f*(fabs(uv[0]-uv[-3]) + fabs(uv[0]-uv[3]));
+                                       
+                                       dx+= 0.25f*(fabs(uv[0]-uvprev[-3]) + fabs(uv[0]-uvnext[-3]));
+                                       dx+= 0.25f*(fabs(uv[0]-uvprev[+3]) + fabs(uv[0]-uvnext[+3]));
+                                       
+                                       /* adaptive sampling, green (V) channel */
+                                       dy= 0.5f*(fabs(uv[1]-uv[-row+1]) + fabs(uv[1]-uv[row+1]));
+                                                        
+                                       dy+= 0.25f*(fabs(uv[1]-uvprev[+1-3]) + fabs(uv[1]-uvnext[+1-3]));
+                                       dy+= 0.25f*(fabs(uv[1]-uvprev[+1+3]) + fabs(uv[1]-uvnext[+1+3]));
+                                       
+                                       /* UV to alpha threshold */
+                                       alpha= 1.0f - threshold*(dx+dy);
+                                       if(alpha<0.0f) alpha= 0.0f;
+                                       else alpha*= uv[2];
+                                       
+                                       /* should use mipmap */
+                                       if(dx > 0.20f) dx= 0.20f;
+                                       if(dy > 0.20f) dy= 0.20f;
+                                       
+                                       ibuf_sample(ibuf, uv[0], uv[1], dx, dy, out);
+                                       /* premul */
+                                       if(alpha<1.0f) {
+                                               out[0]*= alpha;
+                                               out[1]*= alpha;
+                                               out[2]*= alpha;
+                                               out[3]*= alpha;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       IMB_freeImBuf(ibuf);    
+}
+
+
+static void node_composit_exec_mapuv(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(out[0]->hasoutput==0)
+               return;
+       
+       if(in[0]->data && in[1]->data) {
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *uvbuf= in[1]->data;
+               CompBuf *stackbuf;
+               
+               cbuf= typecheck_compbuf(cbuf, CB_RGBA);
+               uvbuf= typecheck_compbuf(uvbuf, CB_VEC3);
+               stackbuf= alloc_compbuf(uvbuf->x, uvbuf->y, CB_RGBA, 1); /* allocs */;
+               
+               do_mapuv(stackbuf, cbuf, uvbuf, 0.05f*(float)node->custom1);
+               
+               out[0]->data= stackbuf;
+               
+               if(cbuf!=in[0]->data)
+                       free_compbuf(cbuf);
+               if(uvbuf!=in[1]->data)
+                       free_compbuf(uvbuf);
+       }
+}
+
+static int node_composit_buts_map_uv(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Alpha:",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
+         &node->custom1, 0, 100, 0, 0, "Conversion percentage of UV differences to Alpha");
+   }
+   return 20;
+}
+
+bNodeType cmp_node_mapuv= {
+       /* type code   */       CMP_NODE_MAP_UV,
+       /* name        */       "Map UV",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS,
+       /* input sock  */       cmp_node_mapuv_in,
+       /* output sock */       cmp_node_mapuv_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_mapuv,
+   /* butfunc     */ node_composit_buts_map_uv
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_mapValue.c b/source/blender/nodes/intern/CMP_nodes/CMP_mapValue.c
new file mode 100644 (file)
index 0000000..412f3b6
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** MAP VALUE ******************** */
+static bNodeSocketType cmp_node_map_value_in[]= {
+       {       SOCK_VALUE, 1, "Value",                 1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_map_value_out[]= {
+       {       SOCK_VALUE, 0, "Value",                 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_map_value(bNode *node, float *out, float *src)
+{
+       TexMapping *texmap= node->storage;
+       
+       out[0]= (src[0] + texmap->loc[0])*texmap->size[0];
+       if(texmap->flag & TEXMAP_CLIP_MIN)
+               if(out[0]<texmap->min[0])
+                       out[0]= texmap->min[0];
+       if(texmap->flag & TEXMAP_CLIP_MAX)
+               if(out[0]>texmap->max[0])
+                       out[0]= texmap->max[0];
+}
+
+static void node_composit_exec_map_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order in: valbuf */
+       /* stack order out: valbuf */
+       if(out[0]->hasoutput==0) return;
+       
+       /* input no image? then only value operation */
+       if(in[0]->data==NULL) {
+               do_map_value(node, out[0]->vec, in[0]->vec);
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
+               
+               composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_map_value, CB_VAL);
+               
+               out[0]->data= stackbuf;
+       }
+}
+
+static int node_composit_buts_map_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      TexMapping *texmap= node->storage;
+      short xstart= (short)butr->xmin;
+      short dy= (short)(butr->ymax-19.0f);
+      short dx= (short)(butr->xmax-butr->xmin)/2;
+
+      uiBlockBeginAlign(block);
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Offs:", xstart, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, "");
+      dy-= 19;
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Size:", xstart, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 3, "");
+      dy-= 23;
+      uiBlockBeginAlign(block);
+      uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC+node->nr, "Min", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", xstart+dx, dy, dx, 19, texmap->min, -1000.0f, 1000.0f, 10, 2, "");
+      dy-= 19;
+      uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC+node->nr, "Max", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
+      uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", xstart+dx, dy, dx, 19, texmap->max, -1000.0f, 1000.0f, 10, 2, "");
+   }
+   return 80;
+};
+
+static void node_composit_init_map_value(bNode* node)
+{
+   node->storage= add_mapping();
+}
+
+bNodeType cmp_node_map_value= {
+       /* type code   */       CMP_NODE_MAP_VALUE,
+       /* name        */       "Map Value",
+       /* width+range */       100, 60, 150,
+       /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_map_value_in,
+       /* output sock */       cmp_node_map_value_out,
+       /* storage     */       "TexMapping",
+       /* execfunc    */       node_composit_exec_map_value,
+   /* butfunc     */ node_composit_buts_map_value,
+                     node_composit_init_map_value
+       
+};
+
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_math.c b/source/blender/nodes/intern/CMP_nodes/CMP_math.c
new file mode 100644 (file)
index 0000000..d867143
--- /dev/null
@@ -0,0 +1,174 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** SCALAR MATH ******************** */ 
+static bNodeSocketType cmp_node_math_in[]= { 
+       { SOCK_VALUE, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f}, 
+       { SOCK_VALUE, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f}, 
+       { -1, 0, "" } 
+};
+
+static bNodeSocketType cmp_node_math_out[]= { 
+       { SOCK_VALUE, 0, "Value", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
+       { -1, 0, "" } 
+};
+
+static void do_math(bNode *node, float *out, float *in, float *in2)
+{
+       switch(node->custom1)
+       {
+       case 0: /* Add */
+               out[0]= in[0] + in2[0]; 
+               break; 
+       case 1: /* Subtract */
+               out[0]= in[0] - in2[0];
+               break; 
+       case 2: /* Multiply */
+               out[0]= in[0] * in2[0]; 
+               break; 
+       case 3: /* Divide */
+               {
+                       if(in[1]==0)    /* We don't want to divide by zero. */
+                               out[0]= 0.0;
+                       else
+                               out[0]= in[0] / in2[0];
+                       }
+               break;
+       case 4: /* Sine */
+               out[0]= sin(in[0]);
+               break;
+       case 5: /* Cosine */
+               out[0]= cos(in[0]);
+               break;
+       case 6: /* Tangent */
+               out[0]= tan(in[0]);
+               break;
+       case 7: /* Arc-Sine */
+               {
+                       /* Can't do the impossible... */
+                       if(in[0] <= 1 && in[0] >= -1 )
+                               out[0]= asin(in[0]);
+                       else
+                               out[0]= 0.0;
+               }
+               break;
+       case 8: /* Arc-Cosine */
+               {
+                       /* Can't do the impossible... */
+                       if( in[0] <= 1 && in[0] >= -1 )
+                               out[0]= acos(in[0]);
+                       else
+                               out[0]= 0.0;
+               }
+               break;
+       case 9: /* Arc-Tangent */
+               out[0]= atan(in[0]);
+               break;
+       case 10: /* Power */
+               {
+                       /* Don't want any imaginary numbers... */
+                       if( in[0] >= 0 )
+                               out[0]= pow(in[0], in2[0]);
+                       else
+                               out[0]= 0.0;
+               }
+               break;
+       case 11: /* Logarithm */
+               {
+                       /* Don't want any imaginary numbers... */
+                       if( in[0] > 0  && in2[0] > 0 )
+                               out[0]= log(in[0]) / log(in2[0]);
+                       else
+                               out[0]= 0.0;
+               }
+               break;
+       case 12: /* Minimum */
+               {
+                       if( in[0] < in2[0] )
+                               out[0]= in[0];
+                       else
+                               out[0]= in2[0];
+               }
+               break;
+       case 13: /* Maximum */
+               {
+                       if( in[0] > in2[0] )
+                               out[0]= in[0];
+                       else
+                               out[0]= in2[0];
+               }
+               break;
+       case 14: /* Round */
+               {
+                               out[0]= (int)(in[0] + 0.5f);
+               }
+               break; 
+       }
+}
+
+static void node_composit_exec_math(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: bw */
+       /* stack order in: col */
+       
+       if(out[0]->hasoutput==0)
+               return;
+       
+       /* input no image? then only color operation */
+       if(in[0]->data==NULL) {
+               do_math(node, out[0]->vec, in[0]->vec, in[1]->vec);
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
+               
+               composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_math, CB_VAL, CB_VAL);
+               
+               out[0]->data= stackbuf;
+       }
+}
+
+bNodeType cmp_node_math= {
+       /* type code   */       CMP_NODE_MATH,
+       /* name        */       "Math",
+       /* width+range */       120, 110, 160,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_math_in,
+       /* output sock */       cmp_node_math_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_math,
+   /* butfunc     */ node_buts_math
+};
+
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c b/source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c
new file mode 100644 (file)
index 0000000..f02a73d
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "../CMP_util.h"
+
+/* **************** MIX RGB ******************** */
+static bNodeSocketType cmp_node_mix_rgb_in[]= {
+       {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 5.0f},
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_mix_rgb_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_mix_rgb(bNode *node, float *out, float *in1, float *in2, float *fac)
+{
+       float col[3];
+       
+       VECCOPY(col, in1);
+       if(node->custom2)
+               ramp_blend(node->custom1, col, col+1, col+2, in2[3]*fac[0], in2);
+       else
+               ramp_blend(node->custom1, col, col+1, col+2, fac[0], in2);
+       VECCOPY(out, col);
+       out[3]= in1[3];
+}
+
+static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order in: fac, Image, Image */
+       /* stack order out: Image */
+       float *fac= in[0]->vec;
+       
+       if(out[0]->hasoutput==0) return;
+       
+       /* input no image? then only color operation */
+       if(in[1]->data==NULL && in[2]->data==NULL) {
+               do_mix_rgb(node, out[0]->vec, in[1]->vec, in[2]->vec, fac);
+       }
+       else {
+               /* make output size of first available input image */
+               CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+               
+               composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, fac, do_mix_rgb, CB_RGBA, CB_RGBA, CB_VAL);
+               
+               out[0]->data= stackbuf;
+       }
+}
+
+/* custom1 = mix type */
+bNodeType cmp_node_mix_rgb= {
+       /* type code   */       CMP_NODE_MIX_RGB,
+       /* name        */       "Mix",
+       /* width+range */       80, 60, 120,
+       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_mix_rgb_in,
+       /* output sock */       cmp_node_mix_rgb_out,
+       /* storage     */       "", 
+       /* execfunc    */       node_composit_exec_mix_rgb,
+   /* butfunc     */ node_buts_mix_rgb
+       
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_normal.c b/source/blender/nodes/intern/CMP_nodes/CMP_normal.c
new file mode 100644 (file)
index 0000000..201dfcf
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** NORMAL  ******************** */
+static bNodeSocketType cmp_node_normal_in[]= {
+       {       SOCK_VECTOR, 1, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketType cmp_node_normal_out[]= {
+       {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
+       {       SOCK_VALUE, 0, "Dot",           1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_normal(bNode *node, float *out, float *in)
+{
+       bNodeSocket *sock= node->outputs.first;
+       float *nor= sock->ns.vec;
+       
+       /* render normals point inside... the widget points outside */
+       out[0]= -INPR(nor, in);
+}
+
+/* generates normal, does dot product */
+static void node_composit_exec_normal(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       bNodeSocket *sock= node->outputs.first;
+       /* stack order input:  normal */
+       /* stack order output: normal, value */
+       
+       /* input no image? then only vector op */
+       if(in[0]->data==NULL) {
+               VECCOPY(out[0]->vec, sock->ns.vec);
+               /* render normals point inside... the widget points outside */
+               out[1]->vec[0]= -INPR(out[0]->vec, in[0]->vec);
+       }
+       else if(out[1]->hasoutput) {
+               /* make output size of input image */
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
+               
+               composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_normal, CB_VEC3);
+               
+               out[1]->data= stackbuf;
+       }
+       
+       
+}
+
+bNodeType cmp_node_normal= {
+       /* type code   */       CMP_NODE_NORMAL,
+       /* name        */       "Normal",
+       /* width+range */       100, 60, 200,
+       /* class+opts  */       NODE_CLASS_OP_VECTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_normal_in,
+       /* output sock */       cmp_node_normal_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_normal,
+   /* butfunc     */ node_buts_normal
+       
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c b/source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c
new file mode 100644 (file)
index 0000000..6963260
--- /dev/null
@@ -0,0 +1,172 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** OUTPUT FILE ******************** */
+static bNodeSocketType cmp_node_output_file_in[]= {
+       {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Z",             0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* image assigned to output */
+       /* stack order input sockets: col, alpha */
+       
+       if(in[0]->data) {
+               RenderData *rd= data;
+               NodeImageFile *nif= node->storage;
+               if(nif->sfra!=nif->efra && (rd->cfra<nif->sfra || rd->cfra>nif->efra)) {
+                       return; /* BAIL OUT RETURN */
+               }
+               else {
+                       CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+                       ImBuf *ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
+                       char string[256];
+                       
+                       ibuf->rect_float= cbuf->rect;
+                       ibuf->dither= rd->dither_intensity;
+                       if(in[1]->data) {
+                               CompBuf *zbuf= in[1]->data;
+                               if(zbuf->type==CB_VAL && zbuf->x==cbuf->x && zbuf->y==cbuf->y) {
+                                       nif->subimtype|= R_OPENEXR_ZBUF;
+                                       ibuf->zbuf_float= zbuf->rect;
+                               }
+                       }
+                       
+                       BKE_makepicstring(string, nif->name, rd->cfra, nif->imtype);
+                       
+                       if(0 == BKE_write_ibuf(ibuf, string, nif->imtype, nif->subimtype, nif->imtype==R_OPENEXR?nif->codec:nif->quality))
+                               printf("Cannot save Node File Output to %s\n", string);
+                       else
+                               printf("Saved: %s\n", string);
+                       
+                       IMB_freeImBuf(ibuf);    
+                       
+                       generate_preview(node, cbuf);
+                       
+                       if(in[0]->data != cbuf) 
+                               free_compbuf(cbuf);
+               }
+       }
+}
+
+
+
+/* allocate sufficient! */
+static void node_imagetype_string(char *str)
+{
+   str += sprintf(str, "Save Image as: %%t|");
+   str += sprintf(str, "Targa %%x%d|", R_TARGA);
+   str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
+   str += sprintf(str, "PNG %%x%d|", R_PNG);
+   str += sprintf(str, "BMP %%x%d|", R_BMP);
+   str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
+   str += sprintf(str, "Iris %%x%d|", R_IRIS);
+   str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
+   str += sprintf(str, "Cineon %%x%d|", R_CINEON);
+   str += sprintf(str, "DPX %%x%d|", R_DPX);
+   str += sprintf(str, "OpenEXR %%x%d", R_OPENEXR);
+}
+
+static int node_composit_buts_output_file(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      NodeImageFile *nif= node->storage;
+      short x= (short)butr->xmin;
+      short y= (short)butr->ymin;
+      short w= (short)butr->xmax-butr->xmin;
+      char str[320];
+
+      node_imagetype_string(str);
+
+      uiBlockBeginAlign(block);
+
+      uiDefBut(block, TEX, B_NOP, "",
+         x, y+60, w, 20, 
+         nif->name, 0.0f, 240.0f, 0, 0, "");
+
+      uiDefButS(block, MENU, B_NOP, str,
+         x, y+40, w, 20, 
+         &nif->imtype, 0.0f, 1.0f, 0, 0, "");
+
+      if(nif->imtype==R_OPENEXR) {
+         uiDefButBitS(block, TOG, R_OPENEXR_HALF, B_REDR, "Half",      
+            x, y+20, w/2, 20, 
+            &nif->subimtype, 0, 0, 0, 0, "");
+
+         uiDefButS(block, MENU,B_NOP, "Codec %t|None %x0|Pxr24 (lossy) %x1|ZIP (lossless) %x2|PIZ (lossless) %x3|RLE (lossless) %x4",  
+            x+w/2, y+20, w/2, 20, 
+            &nif->codec, 0, 0, 0, 0, "");
+      }
+      else {
+         uiDefButS(block, NUM, B_NOP, "Quality: ",
+            x, y+20, w, 20, 
+            &nif->quality, 10.0f, 100.0f, 10, 0, "");
+      }
+
+      /* start frame, end frame */
+      uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra: ", 
+         x, y, w/2, 20, 
+         &nif->sfra, 1, MAXFRAMEF, 10, 0, "");
+      uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "EFra: ", 
+         x+w/2, y, w/2, 20, 
+         &nif->efra, 1, MAXFRAMEF, 10, 0, "");
+
+   }
+   return 80;
+}
+
+static void node_composit_init_output_file(bNode *node)
+{
+   NodeImageFile *nif= MEM_callocN(sizeof(NodeImageFile), "node image file");
+   node->storage= nif;
+   BLI_strncpy(nif->name, G.scene->r.pic, sizeof(nif->name));
+   nif->imtype= G.scene->r.imtype;
+   nif->subimtype= G.scene->r.subimtype;
+   nif->quality= G.scene->r.quality;
+   nif->sfra= G.scene->r.sfra;
+   nif->efra= G.scene->r.efra;
+};
+
+bNodeType cmp_node_output_file= {
+       /* type code   */       CMP_NODE_OUTPUT_FILE,
+       /* name        */       "File Output",
+       /* width+range */       140, 80, 300,
+       /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS,
+       /* input sock  */       cmp_node_output_file_in,
+       /* output sock */       NULL,
+       /* storage     */       "NodeImageFile",
+       /* execfunc    */       node_composit_exec_output_file,
+   /* butfunc     */ node_composit_buts_output_file,
+                     node_composit_init_output_file
+       
+};
\ No newline at end of file
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_rgb.c b/source/blender/nodes/intern/CMP_nodes/CMP_rgb.c
new file mode 100644 (file)
index 0000000..d36d79b
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** RGB ******************** */
+static bNodeSocketType cmp_node_rgb_out[]= {
+       {       SOCK_RGBA, 0, "RGBA",                   0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       bNodeSocket *sock= node->outputs.first;
+       
+       VECCOPY(out[0]->vec, sock->ns.vec);
+}
+
+bNodeType cmp_node_rgb= {
+       /* type code   */       CMP_NODE_RGB,
+       /* name        */       "RGB",
+       /* width+range */       100, 60, 140,
+       /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
+       /* input sock  */       NULL,
+       /* output sock */       cmp_node_rgb_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_rgb,
+   /* butfunc     */ node_buts_rgb
+       
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_rotate.c b/source/blender/nodes/intern/CMP_nodes/CMP_rotate.c
new file mode 100644 (file)
index 0000000..d2291d4
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** Rotate  ******************** */
+
+static bNodeSocketType cmp_node_rotate_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Degr",                  0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_rotate_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+/* function assumes out to be zero'ed, only does RGBA */
+static void bilinear_interpolation_rotate(CompBuf *in, float *out, float u, float v)
+{
+       float *row1, *row2, *row3, *row4, a, b;
+       float a_b, ma_b, a_mb, ma_mb;
+       float empty[4]= {0.0f, 0.0f, 0.0f, 0.0f};
+       int y1, y2, x1, x2;
+
+       x1= (int)floor(u);
+       x2= (int)ceil(u);
+       y1= (int)floor(v);
+       y2= (int)ceil(v);
+
+       /* sample area entirely outside image? */
+       if(x2<0 || x1>in->x-1 || y2<0 || y1>in->y-1)
+               return;
+       
+       /* sample including outside of edges of image */
+       if(x1<0 || y1<0) row1= empty;
+       else row1= in->rect + in->x * y1 * in->type + in->type*x1;
+       
+       if(x1<0 || y2>in->y-1) row2= empty;
+       else row2= in->rect + in->x * y2 * in->type + in->type*x1;
+       
+       if(x2>in->x-1 || y1<0) row3= empty;
+       else row3= in->rect + in->x * y1 * in->type + in->type*x2;
+       
+       if(x2>in->x-1 || y2>in->y-1) row4= empty;
+       else row4= in->rect + in->x * y2 * in->type + in->type*x2;
+       
+       a= u-floor(u);
+       b= v-floor(v);
+       a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
+       
+       out[0]= ma_mb*row1[0] + a_mb*row3[0] + ma_b*row2[0]+ a_b*row4[0];
+       out[1]= ma_mb*row1[1] + a_mb*row3[1] + ma_b*row2[1]+ a_b*row4[1];
+       out[2]= ma_mb*row1[2] + a_mb*row3[2] + ma_b*row2[2]+ a_b*row4[2];
+       out[3]= ma_mb*row1[3] + a_mb*row3[3] + ma_b*row2[3]+ a_b*row4[3];
+}
+
+/* only supports RGBA nodes now */
+static void node_composit_exec_rotate(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       
+       if(out[0]->hasoutput==0)
+               return;
+       
+       if(in[0]->data) {
+               CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* note, this returns zero'd image */
+               float *ofp, rad, u, v, s, c, centx, centy, miny, maxy, minx, maxx;
+               int x, y, yo;
+       
+               rad= (M_PI*in[1]->vec[0])/180.0f;
+               
+               s= sin(rad);
+               c= cos(rad);
+               centx= cbuf->x/2;
+               centy= cbuf->y/2;
+               
+               minx= -centx;
+               maxx= -centx + (float)cbuf->x;
+               miny= -centy;
+               maxy= -centy + (float)cbuf->y;
+               
+               for(y=miny; y<maxy; y++) {
+                       yo= y+(int)centy;
+                       ofp= stackbuf->rect + 4*yo*stackbuf->x;
+                       
+                       for(x=minx; x<maxx; x++, ofp+=4) {
+                               u= c*x + y*s + centx;
+                               v= -s*x + c*y + centy;
+                               
+                               bilinear_interpolation_rotate(cbuf, ofp, u, v);
+                       }
+               }
+               /* rotate offset vector too, but why negative rad, ehh?? Has to be replaced with [3][3] matrix once (ton) */
+               s= sin(-rad);
+               c= cos(-rad);
+               centx= (float)cbuf->xof; centy= (float)cbuf->yof;
+               stackbuf->xof= (int)( c*centx + s*centy);
+               stackbuf->yof= (int)(-s*centx + c*centy);
+               
+               /* pass on output and free */
+               out[0]->data= stackbuf;
+               if(cbuf!=in[0]->data)
+                       free_compbuf(cbuf);
+               
+       }
+}
+
+bNodeType cmp_node_rotate= {
+       /* type code   */       CMP_NODE_ROTATE,
+       /* name        */       "Rotate",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS,
+       /* input sock  */       cmp_node_rotate_in,
+       /* output sock */       cmp_node_rotate_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_rotate,
+   /* butfunc     */ NULL
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_scale.c b/source/blender/nodes/intern/CMP_nodes/CMP_scale.c
new file mode 100644 (file)
index 0000000..709cd55
--- /dev/null
@@ -0,0 +1,149 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** Scale  ******************** */
+
+#define CMP_SCALE_MAX  12000
+
+static bNodeSocketType cmp_node_scale_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "X",                             1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, CMP_SCALE_MAX},
+       {       SOCK_VALUE, 1, "Y",                             1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, CMP_SCALE_MAX},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_scale_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+/* only supports RGBA nodes now */
+/* node->custom1 stores if input values are absolute or relative scale */
+static void node_composit_exec_scale(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       if(out[0]->hasoutput==0)
+               return;
+       
+       if(in[0]->data) {
+               CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+               ImBuf *ibuf;
+               int newx, newy;
+               
+               if(node->custom1==CMP_SCALE_RELATIVE) {
+                       newx= MAX2((int)(in[1]->vec[0]*cbuf->x), 1);
+                       newy= MAX2((int)(in[2]->vec[0]*cbuf->y), 1);
+               }
+               else {  /* CMP_SCALE_ABSOLUTE */
+                       newx= (int)in[1]->vec[0];
+                       newy= (int)in[2]->vec[0];
+               }
+               newx= MIN2(newx, CMP_SCALE_MAX);
+               newy= MIN2(newy, CMP_SCALE_MAX);
+
+               ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
+               if(ibuf) {
+                       ibuf->rect_float= cbuf->rect;
+                       IMB_scaleImBuf(ibuf, newx, newy);
+                       
+                       if(ibuf->rect_float == cbuf->rect) {
+                               /* no scaling happened. */
+                               stackbuf= pass_on_compbuf(in[0]->data);
+                       }
+                       else {
+                               stackbuf= alloc_compbuf(newx, newy, CB_RGBA, 0);
+                               stackbuf->rect= ibuf->rect_float;
+                               stackbuf->malloc= 1;
+                       }
+
+                       ibuf->rect_float= NULL;
+                       ibuf->mall &= ~IB_rectfloat;
+                       IMB_freeImBuf(ibuf);
+                       
+                       /* also do the translation vector */
+                       stackbuf->xof = (int)(((float)newx/(float)cbuf->x) * (float)cbuf->xof);
+                       stackbuf->yof = (int)(((float)newy/(float)cbuf->y) * (float)cbuf->yof);
+               }
+               else {
+                       stackbuf= dupalloc_compbuf(cbuf);
+                       printf("Scaling to %dx%d failed\n", newx, newy);
+               }
+               
+               out[0]->data= stackbuf;
+               if(cbuf!=in[0]->data)
+                       free_compbuf(cbuf);
+       }
+};
+
+static void node_scale_cb(void *node_v, void *unused_v)
+{
+   bNode *node= node_v;
+   bNodeSocket *nsock;
+
+   /* check the 2 inputs, and set them to reasonable values */
+   for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
+      if(node->custom1==CMP_SCALE_RELATIVE)
+         nsock->ns.vec[0]= 1.0;
+      else {
+         if(nsock->next==NULL)
+            nsock->ns.vec[0]= (float)G.scene->r.ysch;
+         else
+            nsock->ns.vec[0]= (float)G.scene->r.xsch;
+      }
+   }   
+}
+
+static int node_composit_buts_scale(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+   if(block) {
+      uiBut *bt= uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Absolute",
+         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
+         &node->custom1, 0, 0, 0, 0, "");
+      uiButSetFunc(bt, node_scale_cb, node, NULL);
+   }
+   return 20;
+};
+
+bNodeType cmp_node_scale= {
+       /* type code   */       CMP_NODE_SCALE,
+       /* name        */       "Scale",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS,
+       /* input sock  */       cmp_node_scale_in,
+       /* output sock */       cmp_node_scale_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_scale,
+   /* butfunc     */ node_composit_buts_scale
+};
+
+
+
+
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_sepcombHSVA.c b/source/blender/nodes/intern/CMP_nodes/CMP_sepcombHSVA.c
new file mode 100644 (file)
index 0000000..df48591
--- /dev/null
@@ -0,0 +1,181 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** SEPARATE HSVA ******************** */
+static bNodeSocketType cmp_node_sephsva_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_sephsva_out[]= {
+       {       SOCK_VALUE, 0, "H",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "S",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "V",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "A",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_sephsva(bNode *node, float *out, float *in)
+{
+       float h, s, v;
+       
+       rgb_to_hsv(in[0], in[1], in[2], &h, &s, &v);
+       
+       out[0]= h;
+       out[1]= s;
+       out[2]= v;
+       out[3]= in[3];
+}
+
+static void node_composit_exec_sephsva(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: bw channels */
+       /* stack order in: col */
+
+       /* input no image? then only color operation */
+       if(in[0]->data==NULL) {
+               float h, s, v;
+       
+               rgb_to_hsv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &h, &s, &v);
+               
+               out[0]->vec[0] = h;
+               out[1]->vec[0] = s;
+               out[2]->vec[0] = v;
+               out[3]->vec[0] = in[0]->vec[3];
+       }
+       else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
+               /* create new buffer so input buffer doesn't get corrupted */
+               CompBuf *cbuf= dupalloc_compbuf(in[0]->data);
+               CompBuf *cbuf2= typecheck_compbuf(cbuf, CB_RGBA);
+
+               /* convert the RGB stackbuf to an HSV representation */
+               composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sephsva, CB_RGBA);
+
+               /* separate each of those channels */
+               if(out[0]->hasoutput)
+                       out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R);
+               if(out[1]->hasoutput)
+                       out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G);
+               if(out[2]->hasoutput)
+                       out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B);
+               if(out[3]->hasoutput)
+                       out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A);
+
+               /*not used anymore */
+               if(cbuf2!=cbuf)
+                       free_compbuf(cbuf2);
+               free_compbuf(cbuf);     
+       }
+}
+
+bNodeType cmp_node_sephsva= {
+       /* type code   */       CMP_NODE_SEPHSVA,
+       /* name        */       "Separate HSVA",
+       /* width+range */       80, 40, 140,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, 0,
+       /* input sock  */       cmp_node_sephsva_in,
+       /* output sock */       cmp_node_sephsva_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_sephsva,
+   /* butfunc     */ NULL
+       
+};
+
+/* **************** COMBINE HSVA ******************** */
+static bNodeSocketType cmp_node_combhsva_in[]= {
+   {   SOCK_VALUE, 1, "H",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+   {   SOCK_VALUE, 1, "S",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+   {   SOCK_VALUE, 1, "V",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+   {   SOCK_VALUE, 1, "A",                     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+   {   -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_combhsva_out[]= {
+   {   SOCK_RGBA, 0, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+   {   -1, 0, ""       }
+};
+
+static void do_comb_hsva(bNode *node, float *out, float *in1, float *in2, float *in3, float *in4)
+{
+   float r,g,b;
+   hsv_to_rgb(in1[0], in2[0], in3[0], &r, &g, &b);
+
+   out[0] = r;
+   out[1] = g;
+   out[2] = b;
+   out[3] = in4[0];
+}
+
+static void node_composit_exec_combhsva(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+   /* stack order out: 1 rgba channels */
+   /* stack order in: 4 value channels */
+
+   /* input no image? then only color operation */
+   if((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
+      out[0]->vec[0] = in[0]->vec[0];
+      out[0]->vec[1] = in[1]->vec[0];
+      out[0]->vec[2] = in[2]->vec[0];
+      out[0]->vec[3] = in[3]->vec[0];
+   }
+   else {
+      /* make output size of first available input image */
+      CompBuf *cbuf;
+      CompBuf *stackbuf;
+
+      /* allocate a CompBuf the size of the first available input */
+      if (in[0]->data) cbuf = in[0]->data;
+      else if (in[1]->data) cbuf = in[1]->data;
+      else if (in[2]->data) cbuf = in[2]->data;
+      else cbuf = in[3]->data;
+
+      stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+
+      composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, 
+         in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, 
+         do_comb_hsva, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
+
+      out[0]->data= stackbuf;
+   }   
+}
+
+bNodeType cmp_node_combhsva= {
+   /* type code   */   CMP_NODE_COMBHSVA,
+   /* name        */   "Combine HSVA",
+   /* width+range */   80, 40, 140,
+   /* class+opts  */   NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+   /* input sock  */   cmp_node_combhsva_in,
+   /* output sock */   cmp_node_combhsva_out,
+   /* storage     */   "",
+   /* execfunc    */   node_composit_exec_combhsva,
+   /* butfunc     */ NULL
+};
+
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_sepcombRGBA.c b/source/blender/nodes/intern/CMP_nodes/CMP_sepcombRGBA.c
new file mode 100644 (file)
index 0000000..8816fab
--- /dev/null
@@ -0,0 +1,157 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** SEPARATE RGBA ******************** */
+static bNodeSocketType cmp_node_seprgba_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_seprgba_out[]= {
+       {       SOCK_VALUE, 0, "R",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "G",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "B",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "A",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_seprgba(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: bw channels */
+       /* stack order in: col */
+       
+       /* input no image? then only color operation */
+       if(in[0]->data==NULL) {
+               out[0]->vec[0] = in[0]->vec[0];
+               out[1]->vec[0] = in[0]->vec[1];
+               out[2]->vec[0] = in[0]->vec[2];
+               out[3]->vec[0] = in[0]->vec[3];
+       }
+       else {
+               /* make sure we get right rgba buffer */
+               CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
+
+               /* don't do any pixel processing, just copy the stack directly (faster, I presume) */
+               if(out[0]->hasoutput)
+                       out[0]->data= valbuf_from_rgbabuf(cbuf, CHAN_R);
+               if(out[1]->hasoutput)
+                       out[1]->data= valbuf_from_rgbabuf(cbuf, CHAN_G);
+               if(out[2]->hasoutput)
+                       out[2]->data= valbuf_from_rgbabuf(cbuf, CHAN_B);
+               if(out[3]->hasoutput)
+                       out[3]->data= valbuf_from_rgbabuf(cbuf, CHAN_A);
+               
+               if(cbuf!=in[0]->data) 
+                       free_compbuf(cbuf);
+
+       }
+}
+
+bNodeType cmp_node_seprgba= {
+       /* type code   */       CMP_NODE_SEPRGBA,
+       /* name        */       "Separate RGBA",
+       /* width+range */       80, 40, 140,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, 0,
+       /* input sock  */       cmp_node_seprgba_in,
+       /* output sock */       cmp_node_seprgba_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_seprgba,
+   /* butfunc     */ NULL
+       
+};
+
+
+/* **************** COMBINE RGBA ******************** */
+static bNodeSocketType cmp_node_combrgba_in[]= {
+       {       SOCK_VALUE, 1, "R",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "G",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "B",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "A",                     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_combrgba_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_combrgba(bNode *node, float *out, float *in1, float *in2, float *in3, float *in4)
+{
+       out[0] = in1[0];
+       out[1] = in2[0];
+       out[2] = in3[0];
+       out[3] = in4[0];
+}
+
+static void node_composit_exec_combrgba(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: 1 rgba channels */
+       /* stack order in: 4 value channels */
+       
+       /* input no image? then only color operation */
+       if((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
+               out[0]->vec[0] = in[0]->vec[0];
+               out[0]->vec[1] = in[1]->vec[0];
+               out[0]->vec[2] = in[2]->vec[0];
+               out[0]->vec[3] = in[3]->vec[0];
+       }
+       else {
+               /* make output size of first available input image */
+               CompBuf *cbuf;
+               CompBuf *stackbuf;
+
+               /* allocate a CompBuf the size of the first available input */
+               if (in[0]->data) cbuf = in[0]->data;
+               else if (in[1]->data) cbuf = in[1]->data;
+               else if (in[2]->data) cbuf = in[2]->data;
+               else cbuf = in[3]->data;
+               
+               stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+               
+               composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, 
+                                                                 in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, 
+                                                                 do_combrgba, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
+               
+               out[0]->data= stackbuf;
+       }       
+}
+
+bNodeType cmp_node_combrgba= {
+       /* type code   */       CMP_NODE_COMBRGBA,
+       /* name        */       "Combine RGBA",
+       /* width+range */       80, 40, 140,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_combrgba_in,
+       /* output sock */       cmp_node_combrgba_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_combrgba,
+   /* butfunc     */ NULL
+       
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_sepcombYCCA.c b/source/blender/nodes/intern/CMP_nodes/CMP_sepcombYCCA.c
new file mode 100644 (file)
index 0000000..8997211
--- /dev/null
@@ -0,0 +1,185 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** SEPARATE YCCA ******************** */
+static bNodeSocketType cmp_node_sepycca_in[]= {
+       {  SOCK_RGBA, 1, "Image",        0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {  -1, 0, ""   }
+};
+static bNodeSocketType cmp_node_sepycca_out[]= {
+       {  SOCK_VALUE, 0, "Y",        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  SOCK_VALUE, 0, "Cb",       0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  SOCK_VALUE, 0, "Cr",       0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  SOCK_VALUE, 0, "A",        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  -1, 0, ""   }
+};
+
+static void do_sepycca(bNode *node, float *out, float *in)
+{
+       float y, cb, cr;
+       
+       rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr);
+       
+       /*divided by 255 to normalize for viewing in */
+       out[0]= y/255.0;
+       out[1]= cb/255.0;
+       out[2]= cr/255.0;
+       out[3]= in[3];
+}
+
+static void node_composit_exec_sepycca(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* input no image? then only color operation */
+       if(in[0]->data==NULL) {
+               float y, cb, cr;
+       
+               rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr);
+       
+               /*divided by 255 to normalize for viewing in */
+               out[0]->vec[0] = y/255.0;
+               out[1]->vec[0] = cb/255.0;
+               out[2]->vec[0] = cr/255.0;
+               out[3]->vec[0] = in[0]->vec[3];
+       }
+       else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
+               /* make copy of buffer so input buffer doesn't get corrupted */
+               CompBuf *cbuf= dupalloc_compbuf(in[0]->data);
+               CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA);
+       
+               /* convert the RGB stackbuf to an HSV representation */
+               composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca, CB_RGBA);
+       
+               /* separate each of those channels */
+               if(out[0]->hasoutput)
+                       out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R);
+               if(out[1]->hasoutput)
+                       out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G);
+               if(out[2]->hasoutput)
+                       out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B);
+               if(out[3]->hasoutput)
+                       out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A);
+
+               /*not used anymore */
+               if(cbuf2!=cbuf)
+                       free_compbuf(cbuf2);
+               free_compbuf(cbuf);
+       }
+}
+
+bNodeType cmp_node_sepycca= {
+       /* type code   */ CMP_NODE_SEPYCCA,
+       /* name        */ "Separate YCbCrA",
+       /* width+range */ 80, 40, 140,
+       /* class+opts  */ NODE_CLASS_CONVERTOR, 0,
+       /* input sock  */ cmp_node_sepycca_in,
+       /* output sock */ cmp_node_sepycca_out,
+       /* storage     */ "",
+       /* execfunc    */ node_composit_exec_sepycca,
+   /* butfunc     */ NULL
+};
+
+
+/* **************** COMBINE YCCA ******************** */
+static bNodeSocketType cmp_node_combycca_in[]= {
+       {       SOCK_VALUE, 1, "Y",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Cb",                    0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Cr",                    0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "A",                     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_combycca_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_comb_ycca(bNode *node, float *out, float *in1, float *in2, float *in3, float *in4)
+{
+       float r,g,b;
+       float y, cb, cr;
+
+       /*need to un-normalize the data*/
+       y=in1[0]*255;
+       cb=in2[0]*255;
+       cr=in3[0]*255;
+
+       ycc_to_rgb(y,cb,cr, &r, &g, &b);
+       
+       out[0] = r;
+       out[1] = g;
+       out[2] = b;
+       out[3] = in4[0];
+}
+
+static void node_composit_exec_combycca(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: 1 ycca channels */
+       /* stack order in: 4 value channels */
+       
+       /* input no image? then only color operation */
+       if((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
+               out[0]->vec[0] = in[0]->vec[0];
+               out[0]->vec[1] = in[1]->vec[0];
+               out[0]->vec[2] = in[2]->vec[0];
+               out[0]->vec[3] = in[3]->vec[0];
+       }
+       else {
+               /* make output size of first available input image */
+               CompBuf *cbuf;
+               CompBuf *stackbuf;
+
+               /* allocate a CompBuf the size of the first available input */
+               if (in[0]->data) cbuf = in[0]->data;
+               else if (in[1]->data) cbuf = in[1]->data;
+               else if (in[2]->data) cbuf = in[2]->data;
+               else cbuf = in[3]->data;
+               
+               stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+               
+               composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, 
+                                                                 in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, 
+                                                                 do_comb_ycca, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
+
+               out[0]->data= stackbuf;
+       }       
+}
+
+bNodeType cmp_node_combycca= {
+       /* type code   */       CMP_NODE_COMBYCCA,
+       /* name        */       "Combine YCbCrA",
+       /* width+range */       80, 40, 140,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_combycca_in,
+       /* output sock */       cmp_node_combycca_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_combycca,
+   /* butfunc     */ NULL
+};
\ No newline at end of file
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_sepcombYUVA.c b/source/blender/nodes/intern/CMP_nodes/CMP_sepcombYUVA.c
new file mode 100644 (file)
index 0000000..6813ffd
--- /dev/null
@@ -0,0 +1,180 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+
+/* **************** SEPARATE YUVA ******************** */
+static bNodeSocketType cmp_node_sepyuva_in[]= {
+       {  SOCK_RGBA, 1, "Image",        0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {  -1, 0, ""   }
+};
+static bNodeSocketType cmp_node_sepyuva_out[]= {
+       {  SOCK_VALUE, 0, "Y",        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  SOCK_VALUE, 0, "U",        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  SOCK_VALUE, 0, "V",        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  SOCK_VALUE, 0, "A",        0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {  -1, 0, ""   }
+};
+
+static void do_sepyuva(bNode *node, float *out, float *in)
+{
+       float y, u, v;
+       
+       rgb_to_yuv(in[0], in[1], in[2], &y, &u, &v);
+       
+       out[0]= y;
+       out[1]= u;
+       out[2]= v;
+       out[3]= in[3];
+}
+
+static void node_composit_exec_sepyuva(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: bw channels */
+       /* stack order in: col */
+       
+       /* input no image? then only color operation */
+       if(in[0]->data==NULL) {
+               float y, u, v;
+       
+               rgb_to_yuv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &u, &v);
+       
+               out[0]->vec[0] = y;
+               out[1]->vec[0] = u;
+               out[2]->vec[0] = v;
+               out[3]->vec[0] = in[0]->vec[3];
+       }
+       else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
+               /* make copy of buffer so input image doesn't get corrupted */
+               CompBuf *cbuf= dupalloc_compbuf(in[0]->data);
+               CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA);
+       
+               /* convert the RGB stackbuf to an YUV representation */
+               composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepyuva, CB_RGBA);
+       
+               /* separate each of those channels */
+               if(out[0]->hasoutput)
+                       out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R);
+               if(out[1]->hasoutput)
+                       out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G);
+               if(out[2]->hasoutput)
+                       out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B);
+               if(out[3]->hasoutput)
+                       out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A);
+
+               /*not used anymore */
+               if(cbuf2!=cbuf)
+                       free_compbuf(cbuf2);
+               free_compbuf(cbuf);
+       }
+}
+
+bNodeType cmp_node_sepyuva= {
+       /* type code   */ CMP_NODE_SEPYUVA,
+       /* name        */ "Separate YUVA",
+       /* width+range */ 80, 40, 140,
+       /* class+opts  */ NODE_CLASS_CONVERTOR, 0,
+       /* input sock  */ cmp_node_sepyuva_in,
+       /* output sock */ cmp_node_sepyuva_out,
+       /* storage     */ "",
+       /* execfunc    */ node_composit_exec_sepyuva,
+   /* butfunc     */ NULL
+};
+
+
+/* **************** COMBINE YUVA ******************** */
+static bNodeSocketType cmp_node_combyuva_in[]= {
+       {       SOCK_VALUE, 1, "Y",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "U",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "V",                     0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "A",                     1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_combyuva_out[]= {
+       {       SOCK_RGBA, 0, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_comb_yuva(bNode *node, float *out, float *in1, float *in2, float *in3, float *in4)
+{
+       float r,g,b;
+       yuv_to_rgb(in1[0], in2[0], in3[0], &r, &g, &b);
+       
+       out[0] = r;
+       out[1] = g;
+       out[2] = b;
+       out[3] = in4[0];
+}
+
+static void node_composit_exec_combyuva(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: 1 rgba channels */
+       /* stack order in: 4 value channels */
+       
+       /* input no image? then only color operation */
+       if((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
+               out[0]->vec[0] = in[0]->vec[0];
+               out[0]->vec[1] = in[1]->vec[0];
+               out[0]->vec[2] = in[2]->vec[0];
+               out[0]->vec[3] = in[3]->vec[0];
+       }
+       else {
+               /* make output size of first available input image */
+               CompBuf *cbuf;
+               CompBuf *stackbuf;
+
+               /* allocate a CompBuf the size of the first available input */
+               if (in[0]->data) cbuf = in[0]->data;
+               else if (in[1]->data) cbuf = in[1]->data;
+               else if (in[2]->data) cbuf = in[2]->data;
+               else cbuf = in[3]->data;
+               
+               stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+               
+               composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, 
+                                                                 in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, 
+                                                                 do_comb_yuva, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
+
+               out[0]->data= stackbuf;
+       }       
+}
+
+bNodeType cmp_node_combyuva= {
+       /* type code   */       CMP_NODE_COMBYUVA,
+       /* name        */       "Combine YUVA",
+       /* width+range */       80, 40, 140,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_combyuva_in,
+       /* output sock */       cmp_node_combyuva_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_combyuva,
+   /* butfunc     */ NULL
+};
+
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c b/source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c
new file mode 100644 (file)
index 0000000..e46d53d
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** SET ALPHA ******************** */
+static bNodeSocketType cmp_node_setalpha_in[]= {
+       {       SOCK_RGBA, 1, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Alpha",                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType cmp_node_setalpha_out[]= {
+       {       SOCK_RGBA, 0, "Image",  0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void node_composit_exec_setalpha(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* stack order out: RGBA image */
+       /* stack order in: col, alpha */
+       
+       /* input no image? then only color operation */
+       if(in[0]->data==NULL) {
+               out[0]->vec[0] = in[0]->vec[0];
+               out[0]->vec[1] = in[0]->vec[1];
+               out[0]->vec[2] = in[0]->vec[2];
+               out[0]->vec[3] = in[1]->vec[0];
+       }
+       else {
+               /* make output size of input image */
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
+               
+               if(in[1]->data==NULL && in[1]->vec[0]==1.0f) {
+                       /* pass on image */
+                       composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_copy_rgb, CB_RGBA);
+               }
+               else {
+                       /* send an compbuf or a value to set as alpha - composit2_pixel_processor handles choosing the right one */
+                       composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
+               }
+       
+               out[0]->data= stackbuf;
+       }
+}
+
+bNodeType cmp_node_setalpha= {
+       /* type code   */       CMP_NODE_SETALPHA,
+       /* name        */       "Set Alpha",
+       /* width+range */       120, 40, 140,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+       /* input sock  */       cmp_node_setalpha_in,
+       /* output sock */       cmp_node_setalpha_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_setalpha,
+   /* butfunc     */ NULL
+       
+};
diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_splitViewer.c b/source/blender/nodes/intern/CMP_nodes/CMP_splitViewer.c
new file mode 100644 (file)
index 0000000..39b7af8
--- /dev/null
@@ -0,0 +1,178 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../CMP_util.h"
+
+/* **************** SPLIT VIEWER ******************** */
+static bNodeSocketType cmp_node_splitviewer_in[]= {
+       {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_copy_split_rgba(bNode *node, float *out, float *in1, float *in2, float *fac)
+{
+       if(*fac==0.0f) {
+               QUATCOPY(out, in1);
+       }
+       else {
+               QUATCOPY(out, in2);
+       }
+}
+
+static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       /* image assigned to output */
+       /* stack order input sockets: image image */
+       
+       if(in[0]->data==NULL || in[1]->data==NULL)
+               return;
+       
+       if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
+               Image *ima= (Image *)node->id;
+               RenderData *rd= data;
+               ImBuf *ibuf;
+               CompBuf *cbuf, *buf1, *buf2, *mask;
+               int x, y;
+               float offset;
+               
+               buf1= typecheck_compbuf(in[0]->data, CB_RGBA);
+               buf2= typecheck_compbuf(in[1]->data, CB_RGBA);
+               
+               BKE_image_user_calc_imanr(node->storage, rd->cfra, 0);
+               
+               /* always returns for viewer image, but we check nevertheless */
+               ibuf= BKE_image_get_ibuf(ima, node->storage);
+               if(ibuf==NULL) {
+                       printf("node_composit_exec_viewer error\n");
+                       return;
+               }
+               
+               /* free all in ibuf */
+               imb_freerectImBuf(ibuf);
+               imb_freerectfloatImBuf(ibuf);
+               IMB_freezbuffloatImBuf(ibuf);
+               
+               /* make ibuf, and connect to ima */
+               ibuf->x= buf1->x;
+               ibuf->y= buf1->y;
+               imb_addrectfloatImBuf(ibuf);
+               
+               ima->ok= IMA_OK_LOADED;
+
+               /* output buf */
+               cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0);      /* no alloc*/
+               cbuf->rect= ibuf->rect_float;
+               
+               /* mask buf */
+               mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1);
+               
+               
+               /* Check which offset mode is selected and limit offset if needed */
+               if(node->custom2 == 0) {
+                       offset = buf1->x / 100.0f * node->custom1;
+                       CLAMP(offset, 0, buf1->x);
+               }
+               else {
+                       offset = buf1->y / 100.0f * node->custom1;
+                       CLAMP(offset, 0, buf1->y);
+               }
+               
+          &n