I would like to write a plugin that returns the complementary color of the one in input, but based on hue value, so that if in input there is a color with a hue value of 0.18, in output there is a color with a hue value of 0.68.
What I have done and what I achieved:
I used VColor.RGBtoHSV to store into 3 variables the HSV values, operated some logic for Hue, used VColor.HSVtoRGB to store the 3 new RGB values.
What is going wrong:
I can’t get the spread of the new variables in output, as I get only one slice
I’m not able to feed FOutput with the new variables, as it returns always a black color - even when it’s not commented out like in this example and with the other numerous tries-, and obviously it’s only one slice
Here’s the code
//called when data for any output pin is requested
public void Evaluate(int SpreadMax)
{
FOutput.SliceCount = SpreadMax;
double[]()Hue = new double[SpreadMax](SpreadMax);
double[]()Sat = new double[SpreadMax](SpreadMax);
double[]()Val = new double[SpreadMax](SpreadMax);
double[]()NRed = new double[SpreadMax](SpreadMax);
double[]()NGre = new double[SpreadMax](SpreadMax);
double[]()NBlu = new double[SpreadMax](SpreadMax);
//This is the reason why I get only one slice in
//output, but if I declare an ISpread<double>
//then I can't store the value coming from
//VColor.RGBtoHSV or .HSVtoRGB
ISpread<Vector4D>[]() Colorz = new ISpread<Vector4D>[](){};
//I was hoping to fit values in here, and then doing
//something like FOutput[i](i)=Colorz[i](i); but to no avail
for (int i = 0; i < SpreadMax; i++)
{
VColor.RGBtoHSV(FInput[i](i).R, FInput[i](i).G, FInput[i](i).B, out Hue[i](i), out Sat[i](i), out Val[i](i));
if (Hue[i](i) <= 0.50)
{
Hue[i](i) = Hue[i](i) + 0.50;
}
else
{
Hue[i](i) = Hue[i](i) - 0.50;
}
VColor.HSVtoRGB(Hue[i](i),Sat[i](i),Val[i](i), out NRed[i](i),out NGre[i](i),out NBlu[i](i));
//Colorz[i](i) = {NRed[i](i),NGre[i](i),NBlu[i](i),Finput[i](i).A};
FO2[i](i) = NRed[i](i);
FO3[i](i) = NGre[i](i);
FO4[i](i) = NBlu[i](i);
FO5[i](i) = FInput[i](i).A;
//FOutput[i](i) = Colorz[i](i);
}
}
}
}
So I think my questions are: how do I declare usable variables in this scenario or, better, since it seems that the variables I declared can store the values from VColor.methods, how to convert them into spreads? How can I feed FOutput with all the values? Please also add any tip you think I should follow.
Thank you for your time.
Yo bro you just need to set your FOutput.Slicecount BEFORE populating it if it’s a spread as, by default, an “Foutput…” Ispread variable (which is a vvvv output pin) has a slice count of 1 and 1 only, so you just need to raise it.
Just add this line before your FOR loop (where you have: “//something like…”);
FOutput.SliceCount = Colorz.Length;
That’s it! One more comment though, you should probably use LISTS instead of ARRAYS, they are much better (you can sort them and do much more with them than arrays).
Let me know if this fixed it otherwise I can look again. Cheers
Sorry I just double checked the code actually you should define colourz as a list and then populate it. I don’t think it will work ISpread Colorz = new ISpread{};
just do something like this:
public List Colorz = new List();
then populate list like this:
float val=0.34;
Colorz.add(val);
Then when it comes to your for loop check do this using .Count instead of .Length to get the number of element in list(list is just a posh array)
FOutput.SliceCount = Colorz.Count;
for (int i = 0; i < Colourz.Count; i++){
…
FOutputi = Colorzi;
etc…}
I think your problem is that when you are defining variable, you define ISPREADS for list or arrays, these are specific just for vvvv INPUT and OUTPUT pin so basically only use “ISpreadxxx = new ISpread…” to define INPUT and OUTPUT pins at the top of your patch then populate your output pins using lists… Hope that’s right now. cheers
Well that’s actually quite easy. No need for arrays and such. See code:
[Input("Input", DefaultColor = new double[](Input("Input", DefaultColor = new double[) { 0.1, 0.2, 0.3, 1.0 })]
public ISpread<RGBAColor> FInput;
[Output("Output")](Output("Output"))
public ISpread<RGBAColor> FOutput;
//called when data for any output pin is requested
public void Evaluate(int SpreadMax)
{
FOutput.SliceCount = SpreadMax;
for (int i = 0; i < SpreadMax; i++)
{
// It's always good practice to store values in a local. Easier
// to read for a human and easier for the compiler to optimize.
var color = FInput[i](i);
// No need for arrays, a local is just fine to do the calculation
double hue, sat, val, nRed, nGre, nBlu;
VColor.RGBtoHSV(color.R, color.G, color.B, out hue, out sat, out val);
if (hue <= 0.50)
hue = hue + 0.50;
else
hue = hue - 0.50;
VColor.HSVtoRGB(hue, sat, val, out nRed, out nGre, out nBlu);
FOutput[i](i) = new RGBAColor(nRed, nGre, nBlu, color.A);
}
}
Aw yiisss.
Thank you Elias- I knew that it would be simple; btw, I hope this could help other newbies out there. @evvvvil: yo man, thank you coz it will probably be of help with other non vvvv related stuff.
Yes, but it does it on RGB values, meaning that from this:
||
R|G|B|H|S|V
0.01|0.37|0.21|0.43|0.97|0.37
||
it returns
||
R|G|B|H|S|V
0.99|0.63|0.79|0.93|0.37|0.99
||
while i want
||
R|G|B|H|S|V
0.37|0.01|0.17|0.93|0.97|0.37
||
Which is quite a different color.
In fact VColor.Complement() - which is the example method in Template (Color) - inverts the color, so that the sum of RGB values of both colors equals 1, giving perfect white (1,1,1).
With what I wanted to do, only hue gets its complement value.
The code is really just what Elias wrote down; make a plugin with it, you’ll notice how Complement (Color) behaves differently from Elias’ code.
Thank you for caring about this, anyway.