Blender V2.61 - r43446

node_composite_levels.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2006 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Bob Holcomb.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "node_composite_util.h"
00034 
00035 
00036 /* **************** LEVELS ******************** */
00037 static bNodeSocketTemplate cmp_node_view_levels_in[]= {
00038     {   SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f},
00039     {   -1, 0, ""   }
00040 };
00041 
00042 static bNodeSocketTemplate cmp_node_view_levels_out[]={
00043     {SOCK_FLOAT, 0,"Mean"},
00044     {SOCK_FLOAT, 0,"Std Dev"},
00045     {-1,0,""}
00046 };
00047 
00048 static void rgb_tobw(float r, float g, float b, float* out)
00049 {
00050     *out= r*0.35f + g*0.45f + b*0.2f;
00051 }
00052 
00053 static void fill_bins(bNode* node, CompBuf* in, int* bins)
00054 {
00055     float value[4];
00056     int ivalue=0;
00057     int x,y;
00058 
00059     /*fill bins */
00060     for(y=0; y<in->y; y++) {
00061         for(x=0; x<in->x; x++) {
00062 
00063             /* get the pixel */
00064             qd_getPixel(in, x, y, value);
00065 
00066             if(value[3] > 0.0f) { /* don't count transparent pixels */
00067                 switch(node->custom1) {
00068                     case 1: { /* all colors */
00069                         rgb_tobw(value[0],value[1],value[2], &value[0]);
00070                         value[0]=value[0]*255; /* scale to 0-255 range */
00071                         ivalue=(int)value[0];
00072                         break;
00073                     }
00074                     case 2: { /* red channel */
00075                         value[0]=value[0]*255; /* scale to 0-255 range */
00076                         ivalue=(int)value[0];
00077                         break;
00078                     }
00079                     case 3:  { /* green channel */
00080                         value[1]=value[1]*255; /* scale to 0-255 range */
00081                         ivalue=(int)value[1];
00082                         break;
00083                     }
00084                     case 4: /*blue channel */
00085                     {
00086                         value[2]=value[2]*255; /* scale to 0-255 range */
00087                         ivalue=(int)value[2];
00088                         break;
00089                     }
00090                     case 5: /* luminence */
00091                     {
00092                         rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]);
00093                         value[0]=value[0]*255; /* scale to 0-255 range */
00094                         ivalue=(int)value[0];
00095                         break;
00096                     }
00097                 } /*end switch */
00098 
00099                 /*clip*/
00100                 if(ivalue<0) ivalue=0;
00101                 if(ivalue>255) ivalue=255;
00102 
00103                 /*put in the correct bin*/
00104                 bins[ivalue]+=1;
00105             } /*end if alpha */
00106         }
00107     }   
00108 }
00109 
00110 static float brightness_mean(bNode* node, CompBuf* in)
00111 {
00112     float sum=0.0;
00113     int numPixels=0.0;
00114     int x,y;
00115     float value[4];
00116 
00117     for(x=0; x< in->x; x++) {
00118         for(y=0; y < in->y; y++) {
00119             
00120             /* get the pixel */
00121             qd_getPixel(in, x, y, value);
00122 
00123             if(value[3] > 0.0f) { /* don't count transparent pixels */
00124                 numPixels++;
00125                 switch(node->custom1)
00126                 {
00127                 case 1:
00128                     {
00129                         rgb_tobw(value[0],value[1],value[2], &value[0]);
00130                         sum+=value[0];
00131                         break;
00132                     }
00133                 case 2:
00134                     {
00135                         sum+=value[0];
00136                         break;
00137                     }
00138                 case 3:
00139                     {
00140                         sum+=value[1];
00141                         break;
00142                     }
00143                 case 4:
00144                     {
00145                         sum+=value[2];
00146                         break;
00147                     }
00148                 case 5:
00149                     {
00150                         rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]);
00151                         sum+=value[0];
00152                         break;
00153                     }
00154                 }
00155             }
00156         }
00157     }
00158 
00159     return sum/numPixels;
00160 }
00161 
00162 static float brightness_standard_deviation(bNode* node, CompBuf* in, float mean)
00163 {
00164     float sum=0.0;
00165     int numPixels=0.0;
00166     int x,y;
00167     float value[4];
00168 
00169     for(x=0; x< in->x; x++) {
00170         for(y=0; y < in->y; y++) {
00171             
00172             /* get the pixel */
00173             qd_getPixel(in, x, y, value);
00174 
00175             if(value[3] > 0.0f) { /* don't count transparent pixels */
00176                 numPixels++;
00177                 switch(node->custom1)
00178                 {
00179                 case 1:
00180                     {
00181                         rgb_tobw(value[0],value[1],value[2], &value[0]);
00182                         sum+=(value[0]-mean)*(value[0]-mean);
00183                         break;
00184                     }
00185                 case 2:
00186                     {
00187                         sum+=value[0];
00188                         sum+=(value[0]-mean)*(value[0]-mean);
00189                         break;
00190                     }
00191                 case 3:
00192                     {
00193                         sum+=value[1];
00194                         sum+=(value[1]-mean)*(value[1]-mean);
00195                         break;
00196                     }
00197                 case 4:
00198                     {
00199                         sum+=value[2];
00200                         sum+=(value[2]-mean)*(value[2]-mean);
00201                         break;
00202                     }
00203                 case 5:
00204                     {
00205                         rgb_to_yuv(value[0],value[1],value[2], &value[0], &value[1], &value[2]);
00206                         sum+=(value[0]-mean)*(value[0]-mean);
00207                         break;
00208                     }
00209                 }
00210             }
00211         }
00212     }
00213 
00214 
00215     return sqrt(sum/(float)(numPixels-1));
00216 }
00217 
00218 static void draw_histogram(bNode *node, CompBuf *out, int* bins)
00219 {
00220     int x,y;
00221     float color[4]; 
00222     float value;
00223     int max;
00224 
00225     /* find max value */
00226     max=0;
00227     for(x=0; x<256; x++) {
00228         if(bins[x]>max) max=bins[x];
00229     }
00230 
00231     /*draw histogram in buffer */
00232     for(x=0; x<out->x; x++) {
00233         for(y=0;y<out->y; y++) {
00234 
00235             /* get normalized value (0..255) */
00236             value=((float)bins[x]/(float)max)*255.0f;
00237 
00238             if(y < (int)value) { /*if the y value is below the height of the bar for this line then draw with the color */
00239                 switch (node->custom1) {
00240                     case 1: { /* draw in black */
00241                         color[0]=0.0; color[1]=0.0; color[2]=0.0; color[3]=1.0;
00242                         break;
00243                     }
00244                     case 2: { /* draw in red */
00245                         color[0]=1.0; color[1]=0.0; color[2]=0.0; color[3]=1.0;
00246                         break;
00247                     }
00248                     case 3: { /* draw in green */
00249                         color[0]=0.0; color[1]=1.0; color[2]=0.0; color[3]=1.0;
00250                         break;
00251                     }
00252                     case 4: { /* draw in blue */
00253                         color[0]=0.0; color[1]=0.0; color[2]=1.0; color[3]=1.0;
00254                         break;
00255                     }
00256                     case 5: { /* draw in white */
00257                         color[0]=1.0; color[1]=1.0; color[2]=1.0; color[3]=1.0;
00258                         break;
00259                     }
00260                 }
00261             }
00262             else{
00263                 color[0]=0.8; color[1]=0.8; color[2]=0.8; color[3]=1.0;
00264             }
00265 
00266             /* set the color */
00267             qd_setPixel(out, x, y, color);
00268         }
00269     }
00270 }
00271 
00272 static void node_composit_exec_view_levels(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
00273 {
00274     CompBuf* cbuf;
00275     CompBuf* histogram;
00276     float mean, std_dev;
00277     int bins[256];
00278     int x;
00279 
00280     if(in[0]->hasinput==0)  return;
00281     if(in[0]->data==NULL) return;
00282 
00283     histogram=alloc_compbuf(256, 256, CB_RGBA, 1);  
00284     cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);   
00285         
00286     /*initalize bins*/
00287     for(x=0; x<256; x++) {
00288         bins[x]=0;
00289     }
00290     
00291     /*fill bins */
00292     fill_bins(node, in[0]->data, bins);
00293 
00294     /* draw the histogram chart */
00295     draw_histogram(node, histogram, bins);
00296 
00297     /* calculate the average brightness and contrast */
00298     mean=brightness_mean(node, in[0]->data);
00299     std_dev=brightness_standard_deviation(node, in[0]->data, mean);
00300 
00301     /*  Printf debuging ;) 
00302     printf("Mean: %f\n", mean);
00303     printf("Std Dev: %f\n", std_dev);
00304     */
00305 
00306     if(out[0]->hasoutput)
00307             out[0]->vec[0]= mean;
00308     if(out[1]->hasoutput)
00309             out[1]->vec[0]= std_dev;
00310 
00311     generate_preview(data, node, histogram);
00312 
00313     if(cbuf!=in[0]->data)
00314         free_compbuf(cbuf);
00315     free_compbuf(histogram);
00316 }
00317 
00318 static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
00319 {
00320     node->custom1=1; /*All channels*/
00321 }
00322 
00323 void register_node_type_cmp_view_levels(bNodeTreeType *ttype)
00324 {
00325     static bNodeType ntype;
00326 
00327     node_type_base(ttype, &ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
00328     node_type_socket_templates(&ntype, cmp_node_view_levels_in, cmp_node_view_levels_out);
00329     node_type_size(&ntype, 140, 100, 320);
00330     node_type_init(&ntype, node_composit_init_view_levels);
00331     node_type_storage(&ntype, "ImageUser", NULL, NULL);
00332     node_type_exec(&ntype, node_composit_exec_view_levels);
00333 
00334     nodeRegisterType(ttype, &ntype);
00335 }