diff options
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/CMP_node.h | 7 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c | 4 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c | 4 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c | 132 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c | 174 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c | 145 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_nodes/CMP_levels.c | 337 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c | 2 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_util.c | 26 | ||||
-rw-r--r-- | source/blender/nodes/intern/CMP_util.h | 5 |
10 files changed, 701 insertions, 135 deletions
diff --git a/source/blender/nodes/CMP_node.h b/source/blender/nodes/CMP_node.h index 020bbdebfa2..041bf1c8361 100644 --- a/source/blender/nodes/CMP_node.h +++ b/source/blender/nodes/CMP_node.h @@ -25,7 +25,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Bob Holcomb. * * ***** END GPL LICENSE BLOCK ***** */ @@ -49,6 +49,7 @@ 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_view_levels; extern bNodeType cmp_node_curve_rgb; extern bNodeType cmp_node_mix_rgb; @@ -88,7 +89,9 @@ extern bNodeType cmp_node_combycca; extern bNodeType cmp_node_premulkey; extern bNodeType cmp_node_diff_matte; -extern bNodeType cmp_node_chroma; +extern bNodeType cmp_node_distance_matte; +extern bNodeType cmp_node_chroma_matte; +extern bNodeType cmp_node_color_matte; extern bNodeType cmp_node_channel_matte; extern bNodeType cmp_node_color_spill; extern bNodeType cmp_node_luma_matte; diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c index d0cc4e5b88d..b0a2531ac1f 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Bob Holcomb * * ***** END GPL LICENSE BLOCK ***** */ @@ -180,7 +180,7 @@ 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->t1= 1.0f; c->t2= 0.0f; c->t3= 0.0f; c->fsize= 0.0f; diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c index 6a40018e659..28b81fe9f47 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c @@ -172,9 +172,9 @@ static void node_composit_init_chroma_matte(bNode *node) c->fstrength= 1.0f; }; -bNodeType cmp_node_chroma={ +bNodeType cmp_node_chroma_matte={ /* *next,*prev */ NULL, NULL, - /* type code */ CMP_NODE_CHROMA, + /* type code */ CMP_NODE_CHROMA_MATTE, /* name */ "Chroma Key", /* width+range */ 200, 80, 300, /* class+opts */ NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS, diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c new file mode 100644 index 00000000000..0a4d3fceff9 --- /dev/null +++ b/source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c @@ -0,0 +1,132 @@ +/** + * $Id: CMP_colorMatte.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** 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): Bob Holcomb + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../CMP_util.h" + +/* ******************* Color Key ********************************************************** */ +static bNodeSocketType cmp_node_color_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_color_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_color_key(bNode *node, float *out, float *in) +{ + NodeChroma *c; + c=node->storage; + + + VECCOPY(out, in); + + if(fabs(in[0]-c->key[0]) < c->t1 && + fabs(in[1]-c->key[1]) < c->t2 && + fabs(in[2]-c->key[2]) < c->t3) + { + out[3]=0.0; /*make transparent*/ + } + + else { /*pixel is outside key color */ + out[3]=in[3]; /* make pixel just as transparent as it was before */ + } +} + +static void node_composit_exec_color_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + CompBuf *cbuf; + CompBuf *colorbuf; + 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); + + colorbuf= dupalloc_compbuf(cbuf); + + c=node->storage; + + /*convert rgbbuf to hsv*/ + composit1_pixel_processor(node, colorbuf, cbuf, in[0]->vec, do_rgba_to_hsva, CB_RGBA); + + /*convert key to hsv*/ + do_rgba_to_hsva(node, c->key, in[1]->vec); + + + /*per pixel color key*/ + composit1_pixel_processor(node, colorbuf, colorbuf, in[0]->vec, do_color_key, CB_RGBA); + + /*convert back*/ + composit1_pixel_processor(node, colorbuf, colorbuf, in[0]->vec, do_hsva_to_rgba, CB_RGBA); + + out[0]->data= colorbuf; + if(out[1]->hasoutput) + out[1]->data= valbuf_from_rgbabuf(colorbuf, CHAN_A); + + generate_preview(node, colorbuf); + + if(cbuf!=in[0]->data) + free_compbuf(cbuf); +}; + +static void node_composit_init_color_matte(bNode *node) +{ + NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node color"); + node->storage= c; + c->t1= 0.01f; + c->t2= 0.1f; + c->t3= 0.1f; + c->fsize= 0.0f; + c->fstrength= 1.0f; +}; + +bNodeType cmp_node_color_matte={ + /* *next,*prev */ NULL, NULL, + /* type code */ CMP_NODE_COLOR_MATTE, + /* name */ "Color Key", + /* width+range */ 200, 80, 300, + /* class+opts */ NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS, + /* input sock */ cmp_node_color_in, + /* output sock */ cmp_node_color_out, + /* storage */ "NodeChroma", + /* execfunc */ node_composit_exec_color_matte, + /* butfunc */ NULL, + /* initfunc */ node_composit_init_color_matte, + /* freestoragefunc */ node_free_standard_storage, + /* copystoragefunc */ node_copy_standard_storage, + /* id */ NULL +}; + + diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c index ade2111f246..68a1bcd5471 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Bob Holcomb * * ***** END GPL LICENSE BLOCK ***** */ @@ -31,8 +31,8 @@ /* ******************* 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}, + {SOCK_RGBA,1,"Image 1", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + {SOCK_RGBA,1,"Image 2", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, {-1,0,""} }; @@ -44,157 +44,85 @@ static bNodeSocketType cmp_node_diff_matte_out[]={ /* 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) +static void do_diff_matte(bNode *node, float *colorbuf, float *imbuf1, float *imbuf2) { NodeChroma *c= (NodeChroma *)node->storage; - float *keymin= keyvals; - float *keymax= keyvals+3; - float *key= keyvals+6; - float tolerance= keyvals[9]; - float distance, alpha; + float tolerence=c->t1; + float falloff=c->t2; + float difference; + float 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; + difference=fabs(imbuf2[0]-imbuf1[0])+ + fabs(imbuf2[1]-imbuf1[1])+ + fabs(imbuf2[2]-imbuf1[2]); + + /*average together the distances*/ + difference=difference/3.0; + + VECCOPY(colorbuf, imbuf1); + + /*make 100% transparent*/ + if(difference < tolerence){ + colorbuf[3]=0.0; } + /*in the falloff region, make partially transparent */ + else if(difference < falloff+tolerence){ + difference=difference-tolerence; + alpha=difference/falloff; + /*only change if more transparent than before */ + if(alpha < imbuf1[3]) { + colorbuf[3]=alpha; + } + else { /* leave as before */ + colorbuf[3]=imbuf1[3]; + } + } else { /*foreground object*/ - colorbuf[3]= inbuf[3]; + colorbuf[3]= imbuf1[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; + CompBuf *outbuf; + CompBuf *imbuf1; + CompBuf *imbuf2; 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; + if(in[1]->data==NULL) return; - inbuf=typecheck_compbuf(in[0]->data, CB_RGBA); + imbuf1=typecheck_compbuf(in[0]->data, CB_RGBA); + imbuf2=typecheck_compbuf(in[1]->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])); + outbuf=dupalloc_compbuf(imbuf1); /* 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); + composit2_pixel_processor(node, outbuf, imbuf1, in[0]->vec, imbuf2, in[1]->vec, do_diff_matte, CB_RGBA, CB_RGBA); - /*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; + out[0]->data=outbuf; if(out[1]->hasoutput) - out[1]->data=valbuf_from_rgbabuf(workbuf, CHAN_A); - generate_preview(node, workbuf); + out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A); + generate_preview(node, outbuf); + + if(imbuf1!=in[0]->data) + free_compbuf(imbuf1); - if(inbuf!=in[0]->data) - free_compbuf(inbuf); + if(imbuf2!=in[1]->data) + free_compbuf(imbuf2); } 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 */ + c->t1= 0.1f; + c->t2= 0.1f; } bNodeType cmp_node_diff_matte={ diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c new file mode 100644 index 00000000000..921ac869cb8 --- /dev/null +++ b/source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c @@ -0,0 +1,145 @@ +/** + * $Id: CMP_diffMatte.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** 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): Bob Holcomb + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../CMP_util.h" + +/* ******************* channel Distance Matte ********************************* */ +static bNodeSocketType cmp_node_distance_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_distance_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_distance_matte(bNode *node, float *out, float *in) +{ + NodeChroma *c= (NodeChroma *)node->storage; + float tolerence=c->t1; + float falloff=c->t2; + float distance; + float alpha; + + distance=sqrt((c->key[0]-in[0])*(c->key[0]-in[0]) + + (c->key[1]-in[1])*(c->key[1]-in[1]) + + (c->key[2]-in[2])*(c->key[2]-in[2])); + + VECCOPY(out, in); + + /*make 100% transparent */ + if(distance < tolerence) { + out[3]=0.0; + } + /*in the falloff region, make partially transparent */ + else if(distance < falloff+tolerence){ + distance=distance-tolerence; + alpha=distance/falloff; + /*only change if more transparent than before */ + if(alpha < in[3]) { + out[3]=alpha; + } + else { /* leave as before */ + out[3]=in[3]; + } + } + else { + out[3]=in[3]; + } +} + +static void node_composit_exec_distance_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; + + /*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*/ + c->key[0]= in[1]->vec[0]; + c->key[1]= in[1]->vec[1]; + c->key[2]= in[1]->vec[2]; + + /* note, processor gets a keyvals array passed on as buffer constant */ + composit1_pixel_processor(node, workbuf, workbuf, in[0]->vec, do_distance_matte, CB_RGBA); + + + 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 void node_composit_init_distance_matte(bNode *node) +{ + NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); + node->storage= c; + c->t1= 0.1f; + c->t2= 0.1f; +} + +bNodeType cmp_node_distance_matte={ + /* *next,*prev */ NULL, NULL, + /* type code */ CMP_NODE_DIST_MATTE, + /* name */ "Distance Key", + /* width+range */ 200, 80, 250, + /* class+opts */ NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS, + /* input sock */ cmp_node_distance_matte_in, + /* output sock */ cmp_node_distance_matte_out, + /* storage */ "NodeChroma", + /* execfunc */ node_composit_exec_distance_matte, + /* butfunc */ NULL, + /* initfunc */ node_composit_init_distance_matte, + /* freestoragefunc */ node_free_standard_storage, + /* copystoragefunc */ node_copy_standard_storage, + /* id */ NULL +}; + + diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_levels.c b/source/blender/nodes/intern/CMP_nodes/CMP_levels.c new file mode 100644 index 00000000000..414c535789e --- /dev/null +++ b/source/blender/nodes/intern/CMP_nodes/CMP_levels.c @@ -0,0 +1,337 @@ +/** + * $Id: CMP_levels.c 12931 2007-12-17 18:20:48Z theeth $ + * + * ***** 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): Bob Holcomb. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../CMP_util.h" + + +/* **************** LEVELS ******************** */ +static bNodeSocketType cmp_node_view_levels_in[]= { + { SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketType cmp_node_view_levels_out[]={ + {SOCK_VALUE, 0,"Mean",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + {SOCK_VALUE, 0,"Std Dev",0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + {-1,0,""} +}; + +static void rgb_tobw(float r, float g, float b, float* out) +{ + *out= r*0.35f + g*0.45f + b*0.2f; +} + +static void fill_bins(bNode* node, CompBuf* in, int* bins) +{ + float value[4]; + int ivalue; + int x,y; + + /*fill bins */ + for(y=0; y<in->y; y++) { + for(x=0; x<in->x; x++) { + + /* get the pixel */ + qd_getPixel(in, x, y, value); + + if(value[3] > 0.0) { /* don't count transparent pixels */ + switch(node->custom1) { + case 1: { /* all colors */ + rgb_tobw(value[0],value[1],value[2], &value[0]); + value[0]=value[0]*255; /* scale to 0-255 range */ + ivalue=(int)value[0]; + break; + } + case 2: { /* red channel */ + value[0]=value[0]*255; /* scale to 0-255 range */ + ivalue=(int)value[0]; + break; + } + case 3: { /* green channel */ + value[1]=value[1]*255; /* scale to 0-255 range */ + ivalue=(int)value[1]; + break; + } + case 4: /*blue channel */ + { + value[2]=value[2]*255; /* scale to 0-255 range */ + ivalue=(int)value[2]; + break; + } + case 5: /* luminence */ + { + rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]); + value[0]=value[0]*255; /* scale to 0-255 range */ + ivalue=(int)value[0]; + break; + } + } /*end switch */ + + /*clip*/ + if(ivalue<0) ivalue=0; + if(ivalue>255) ivalue=255; + + /*put in the correct bin*/ + bins[ivalue]+=1; + } /*end if alpha */ + } + } +} + +static float brightness_mean(bNode* node, CompBuf* in) +{ + float sum=0.0; + int numPixels=0.0; + int x,y; + float value[4]; + + for(x=0; x< in->x; x++) { + for(y=0; y < in->y; y++) { + + /* get the pixel */ + qd_getPixel(in, x, y, value); + + if(value[3] > 0.0) { /* don't count transparent pixels */ + numPixels++; + switch(node->custom1) + { + case 1: + { + rgb_tobw(value[0],value[1],value[2], &value[0]); + sum+=value[0]; + break; + } + case 2: + { + sum+=value[0]; + break; + } + case 3: + { + sum+=value[1]; + break; + } + case 4: + { + sum+=value[2]; + break; + } + case 5: + { + rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]); + sum+=value[0]; + break; + } + } + } + } + } + + return sum/numPixels; +} + +static float brightness_standard_deviation(bNode* node, CompBuf* in, float mean) +{ + float sum=0.0; + int numPixels=0.0; + int x,y; + float value[4]; + + for(x=0; x< in->x; x++) { + for(y=0; y < in->y; y++) { + + /* get the pixel */ + qd_getPixel(in, x, y, value); + + if(value[3] > 0.0) { /* don't count transparent pixels */ + numPixels++; + switch(node->custom1) + { + case 1: + { + rgb_tobw(value[0],value[1],value[2], &value[0]); + sum+=(value[0]-mean)*(value[0]-mean); + break; + } + case 2: + { + sum+=value[0]; + sum+=(value[0]-mean)*(value[0]-mean); + break; + } + case 3: + { + sum+=value[1]; + sum+=(value[1]-mean)*(value[1]-mean); + break; + } + case 4: + { + sum+=value[2]; + sum+=(value[2]-mean)*(value[2]-mean); + break; + } + case 5: + { + rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]); + sum+=(value[0]-mean)*(value[0]-mean); + break; + } + } + } + } + } + + + return sqrt(sum/(float)(numPixels-1)); +} + +static void draw_histogram(bNode *node, CompBuf *out, int* bins) +{ + int x,y; + float color[4]; + float value; + int max; + + /* find max value */ + max=0; + for(x=0; x<256; x++) { + if(bins[x]>max) max=bins[x]; + } + + /*draw histogram in buffer */ + for(x=0; x<out->x; x++) { + for(y=0;y<out->y; y++) { + + /* get normalized value (0..255) */ + value=((float)bins[x]/(float)max)*255.0; + + if(y < (int)value) { /*if the y value is below the height of the bar for this line then draw with the color */ + switch (node->custom1) { + case 1: { /* draw in black */ + color[0]=0.0; color[1]=0.0; color[2]=0.0; color[3]=1.0; + break; + } + case 2: { /* draw in red */ + color[0]=1.0; color[1]=0.0; color[2]=0.0; color[3]=1.0; + break; + } + case 3: { /* draw in green */ + color[0]=0.0; color[1]=1.0; color[2]=0.0; color[3]=1.0; + break; + } + case 4: { /* draw in blue */ + color[0]=0.0; color[1]=0.0; color[2]=1.0; color[3]=1.0; + break; + } + case 5: { /* draw in white */ + color[0]=1.0; color[1]=1.0; color[2]=1.0; color[3]=1.0; + break; + } + } + } + else{ + color[0]=0.8; color[1]=0.8; color[2]=0.8; color[3]=1.0; + } + + /* set the color */ + qd_setPixel(out, x, y, color); + } + } +} + +static void node_composit_exec_view_levels(void *data, bNode *node, bNodeStack **in, bNodeStack **out) +{ + CompBuf* cbuf; + CompBuf* histogram; + float mean, std_dev; + int bins[256]; + int x; + + if(in[0]->hasinput==0) return; + if(in[0]->data==NULL) return; + + histogram=alloc_compbuf(256, 256, CB_RGBA, 1); + cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); + + /*initalize bins*/ + for(x=0; x<256; x++) { + bins[x]=0; + } + + /*fill bins */ + fill_bins(node, in[0]->data, bins); + + /* draw the histogram chart */ + draw_histogram(node, histogram, bins); + + /* calculate the average brightness and contrast */ + mean=brightness_mean(node, in[0]->data); + std_dev=brightness_standard_deviation(node, in[0]->data, mean); + + /* Printf debuging ;) + printf("Mean: %f\n", mean); + printf("Std Dev: %f\n", std_dev); + */ + + if(out[0]->hasoutput) + out[0]->vec[0]= mean; + if(out[1]->hasoutput) + out[1]->vec[0]= std_dev; + + generate_preview(node, histogram); + + if(cbuf!=in[0]->data) + free_compbuf(cbuf); + free_compbuf(histogram); +} + +static void node_composit_init_view_levels(bNode* node) +{ + node->custom1=1; /*All channels*/ +} + +bNodeType cmp_node_view_levels= { + /* *next,*prev */ NULL, NULL, + /* type code */ CMP_NODE_VIEW_LEVELS, + /* name */ "Levels", + /* widthrange */ 140, 100, 320, + /* classopts */ NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW, + /* input sock */ cmp_node_view_levels_in, + /* output sock */ cmp_node_view_levels_out, + /* storage */ "ImageUser", + /* execfunc */ node_composit_exec_view_levels, + /* butfunc */ NULL, + /* initfunc */ node_composit_init_view_levels, + /* freestoragefunc */ node_free_standard_storage, + /* copystoragefunc */ node_copy_standard_storage, + /* id */ NULL + +}; + diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c index 9aebd999b29..350def76736 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Bob Holcomb . * * ***** END GPL LICENSE BLOCK ***** */ diff --git a/source/blender/nodes/intern/CMP_util.c b/source/blender/nodes/intern/CMP_util.c index f9805645115..b396d5549d7 100644 --- a/source/blender/nodes/intern/CMP_util.c +++ b/source/blender/nodes/intern/CMP_util.c @@ -1104,9 +1104,23 @@ void qd_getPixel(CompBuf* src, int x, int y, float* col) { if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { float* bc = &src->rect[(x + y*src->x)*src->type]; - col[0] = bc[0], col[1] = bc[1], col[2] = bc[2]; + switch(src->type){ + /* these fallthrough to get all the channels */ + case CB_RGBA: col[3]=bc[3]; + case CB_VEC3: col[2]=bc[2]; + case CB_VEC2: col[1]=bc[1]; + case CB_VAL: col[0]=bc[0]; + } + } + else { + switch(src->type){ + /* these fallthrough to get all the channels */ + case CB_RGBA: col[3]=0.0; + case CB_VEC3: col[2]=0.0; + case CB_VEC2: col[1]=0.0; + case CB_VAL: col[0]=0.0; + } } - else col[0] = col[1] = col[2] = 0.f; } // sets pixel (x, y) to color col @@ -1114,7 +1128,13 @@ void qd_setPixel(CompBuf* src, int x, int y, float* col) { if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { float* bc = &src->rect[(x + y*src->x)*src->type]; - bc[0] = col[0], bc[1] = col[1], bc[2] = col[2]; + switch(src->type){ + /* these fallthrough to get all the channels */ + case CB_RGBA: bc[3]=col[3]; + case CB_VEC3: bc[2]=col[2]; + case CB_VEC2: bc[1]=col[1]; + case CB_VAL: bc[0]=col[0]; + } } } diff --git a/source/blender/nodes/intern/CMP_util.h b/source/blender/nodes/intern/CMP_util.h index 19e41f5c118..2a2dc97ed73 100644 --- a/source/blender/nodes/intern/CMP_util.h +++ b/source/blender/nodes/intern/CMP_util.h @@ -168,7 +168,7 @@ typedef float fRGB[4]; /* clear color */ #define fRGB_clear(c) { c[0]=c[1]=c[2]=0.f; } /* copy c2 to c1 */ -#define fRGB_copy(c1, c2) { c1[0]=c2[0]; c1[1]=c2[1]; c1[2]=c2[2]; } +#define fRGB_copy(c1, c2) { c1[0]=c2[0]; c1[1]=c2[1]; c1[2]=c2[2]; c1[3]=c2[3]; } /* add c2 to c1 */ #define fRGB_add(c1, c2) { c1[0]+=c2[0]; c1[1]+=c2[1]; c1[2]+=c2[2]; } /* subtract c2 from c1 */ @@ -186,7 +186,8 @@ typedef float fRGB[4]; /* swap colors c1 & c2 */ #define fRGB_swap(c1, c2) { float _t=c1[0]; c1[0]=c2[0]; c2[0]=_t;\ _t=c1[1]; c1[1]=c2[1]; c2[1]=_t;\ - _t=c1[2]; c1[2]=c2[2]; c2[2]=_t; } + _t=c1[2]; c1[2]=c2[2]; c2[2]=_t;\ + _t=c1[3]; c1[3]=c2[3]; c3[3]=_t;} void qd_getPixel(CompBuf* src, int x, int y, float* col); void qd_setPixel(CompBuf* src, int x, int y, float* col); |