It doesn't quite work yet, because I have virtually NO clue about what I'm doing in CPP

Anyway, the idea is to get the averages of the 3 color-channels and then push or pull the red and blue in the direction of the green at each single level (from 0 to 255).

So kind of like a whitebalance that does it at 256 different stages.

The idea I have tried to see if I could program into the cpp-script, is one that tries to factor in the difference between the green to red and green to blue, and then move the red and blue with their individual factors. This is to avoid the image being perfectly whitebalanced (and thus turning grey-scale)

For example; at the green value of 100; if the red is between 50 and 60 (average 55) = add 45 to red channel's original value (so it becomes 95 to 105, IE a new average value of 100 while still leaving in the differences so that color remains)

I don't know if such a whitebalance idea will even work, but here's the code I have so far (which is really not working too well, but does indeed do something along what I'm trying)

I'm posting it here if somebody with CPP-skills wants to have a go at it.

Code: Select all

```
//##NAME:Redistribute
//##DESCRIPTION:Gaussian redistribution of histogram
//##INPUTS:1
//##VAR1:60
//##VAR1_NAME:Sigma (gauss width)
//##VAR2:50
//##VAR2_NAME:Mean (shift)
// Please retain this intro-comment
// This software is FREE!! Open Source software, do what you want with it, open to the community, etc.....
// GNU General Public License
// see http://www.gnu.org/licenses/gpl-2.0.html
// Inspired by: Fred Weinhaus has developed a script, called "redist" for imagemagick
// It redistributes the histogram of an image into a uniform distribution, while appling the same change to all color channels equally.
// modified and adapted for Photo-Reactor Script-block by Oscar
int SHOWGRAPH = 0;
void countRedist(image &img)
{
int width = img.width;
int height = img.height;
////////////////// MAX
float maximum = 1;
float maximumgauss = 1;
////////////////// MIN
int minimum = 65535;
float minimumgauss =65535;
//////HISTOGRAM
int[] histogram(256);
int[] countR(256);
int[] countG(256);
int[] countB(256);
int[] valueR(256);
int[] valueG(256);
int[] valueB(256);
for (int z=0; z< 256; z++)
histogram[z] = 0;
for (int zR=0; zR< 256; zR++)
countR[zR] = 0;
for (int zG=0; zG< 256; zG++)
countG[zG] = 0;
for (int zB=0; zB< 256; zB++)
countB[zB] = 0;
for (int zvR=0; zvR< 256; zvR++)
valueR[zvR] = 0;
for (int zvG=0; zvG< 256; zvG++)
valueG[zvG] = 0;
for (int zvB=0; zvB< 256; zvB++)
valueB[zvB] = 0;
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
// one way to get color from pixel
pixel color = img.Pixel(x,y);
// Average
int gray = (color.r+color.g+color.b)/3;
// luminosity
// int gray = (0.21*color.r+0.72*color.g+0.07*color.b);
if (gray>255) gray =255;
histogram[gray] +=1;
if (histogram[gray]>maximum) maximum = histogram[gray];
int G = color.g;
if (G>255) G =255;
countG[G] +=1;
valueG[G] = valueG[G] + G;
//if (countG[G]>maximum) maximum = countG[G];
int R = color.r;
if (R>255) R =255;
countR[R] +=1;
//valueR[R] = valueR[R] + R;
valueR[G] = valueR[G] + R;
//if (countR[R]>maximum) maximum = countR[R];
int B = color.b;
if (B>255) B =255;
countB[B] +=1;
//valueB[B] = valueB[B] + B;
valueB[G] = valueB[G] + B;
//if (countB[B]>maximum) maximum = countB[B];
}
}
float fx = width/256.0;
// display gray histogram
// this is for testing purposes
if (SHOWGRAPH>0)
for (int x=0; x<255; x++)
{
float nhisto = (histogram[x]/maximum);
int ypos = nhisto*height;
if (ypos>height-1) ypos = height-1;
for (int y=0; y<ypos; y++)
{
pixel color = img.Pixel(x*fx, height-y-1);
img.SetRGB(x*fx, height-y-1, (255+color.r)/2, (255+color.g)/2, (255+color.b)/2);
img.SetRGB(x*fx+1, height-y-1, (255+color.r)/2, (255+color.g)/2, (255+color.b)/2);
}
img.SetRGB(x*fx, height-ypos-1, 0, 0, 0);
}
//make cummulative
int cumulative = 0;
for (int x=0; x<256; x++)
{
cumulative += histogram[x];
histogram[x] = cumulative;
}
maximum = histogram[255];
minimum = 0;
//enerate gaussian distribution graph
int[] gaussian(256);
for (int z=0; z< 256; z++)
gaussian[z] = 0;
double temp;
int KSize = (VAR2*2.55); // mean
float sigma = VAR1;
for (int j= 0; j< 256; j++)
{
temp = (j-KSize)/sigma;
gaussian[j] = 256* (pow(2.71828,-temp * temp / 2.0));
if (gaussian[j]>maximumgauss) maximumgauss = gaussian[j];
//traceint(gaussian[j]);
}
// display gaussian
// this is for testing purposes
if (SHOWGRAPH>0)
for (int x=0; x<255; x++)
{
float nhisto = (gaussian[x]/maximumgauss);
int ypos = nhisto*height;
if (ypos>height-1) ypos = height-1;
for (int y=0; y<ypos; y++)
{
pixel color = img.Pixel(x*fx, height-y-1);
img.SetRGB(x*fx, height-y-1, color.r/2, color.g/2, (255+color.b)/2);
}
img.SetRGB(x*fx, height-ypos-1, 0, 0, 0);
}
cumulative = 0;
for (int x=0; x<256; x++)
{
cumulative += gaussian[x];
gaussian[x] = cumulative;
}
maximumgauss = gaussian[255];
minimumgauss = 0;
// move the normal histogram to the gaussian historgram
int[] clut(256);
int[] clutR(256);
int[] clutG(256);
int[] clutB(256);
int k=0;
for (int j=0; j<256; j++ )
{
while ( k<255 && (gaussian[k]/maximumgauss <= histogram[j]/maximum ))
{
k++;
}
clut[j] = k;
//traceint (clut[j]);
clutG[j] = (valueG[j] / (countG[j] + 0.01));
//clutR[j] = clutG[j];
//clutB[j] = clutG[j];
clutR[j] = clutG[j] + (clutG[j] - (valueR[j] / (countG[j] + 0.01)));
clutB[j] = clutG[j] + (clutG[j] - (valueB[j] / (countG[j] + 0.01)));
//clutR[j] = (valueR[j] / (countG[j] + 0.01));
//clutB[j] = (valueB[j] / (countG[j] + 0.01));
}
// now we have lut
// apply it to the image
int r,g,b;
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
// one way to get color from pixel
pixel color = img.Pixel(x,y);
r = clutR[color.r];
g = clutG[color.g];
b = clutB[color.b];
img.SetRGB(x, y, r, g, b);
}
}
// display curve
// this is for testing purposes
if (SHOWGRAPH>0)
for (int x=0; x<255; x++)
{
float nhisto = clut[x]/255.0;
int ypos = nhisto*height;
if (ypos>height-1) ypos = height-1;
img.SetRGB(x*fx, height-ypos-1,255, 0, 0);
img.SetRGB(x*fx+1, height-ypos-1,255, 0, 0);
}
}
void main()
{
// get the image from input socket
image img(INPUT);
// sample function call
countRedist(img);
// send the image to output
img.SetOutput();
}
```