Blender V2.61 - r43446
|
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 }