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