This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/nodes/intern/CMP_nodes/CMP_levels.c

346 lines
7.8 KiB
C

/**
* $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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, int colorcor)
{
float value[4];
int ivalue=0;
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 */
if(colorcor)
linearrgb_to_srgb_v3_v3(&value[0],&value[0]);
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 */
if(colorcor)
value[0]=linearrgb_to_srgb(value[0]);
value[0]=value[0]*255; /* scale to 0-255 range */
ivalue=(int)value[0];
break;
}
case 3: { /* green channel */
if(colorcor)
value[1]=linearrgb_to_srgb(value[1]);
value[1]=value[1]*255; /* scale to 0-255 range */
ivalue=(int)value[1];
break;
}
case 4: /*blue channel */
{
if(colorcor)
value[2]=linearrgb_to_srgb(value[2]);
value[2]=value[2]*255; /* scale to 0-255 range */
ivalue=(int)value[2];
break;
}
case 5: /* luminence */
{
if(colorcor)
linearrgb_to_srgb_v3_v3(&value[0],&value[0]);
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;
RenderData *rd=data;
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, rd->color_mgt_flag & R_COLOR_MANAGEMENT);
/* 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(data, 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*/
}
void register_node_type_cmp_view_levels(ListBase *lb)
{
static bNodeType ntype;
node_type_base(&ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW,
cmp_node_view_levels_in, cmp_node_view_levels_out);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_view_levels);
node_type_storage(&ntype, "ImageUser", NULL, NULL);
node_type_exec(&ntype, node_composit_exec_view_levels);
nodeRegisterType(lb, &ntype);
}