Help with variable declaration


I need some help with the following issue.

What I want to do:

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;
						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.

Bringing this back to first page (3.1 kB)

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;

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;

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;

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;
            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.

elias saves the day again, nice touch elias. :) so simple

Good that you learned how to to this in c#!

Now I just have to check if you are aware of the Complement (color) node?

Yes, but it does it on RGB values, meaning that from this:


it returns

while i want


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.