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();

}