How to extract values from a Color Setter?

i have a simple Color Setter :

{ColorSetter[Dynamic[y]], Dynamic[y]}

How do I get the vales of the selected color into a variable?
As an example, I would like to acces the Hue from “HSB”

The following srcipts don’t work :

ee ={ColorSetter[Dynamic[y]], Dynamic[y]}
ee = Setting[{ColorSetter[Dynamic[y]], Dynamic[y]}]
ee = Setting[Hue[{ColorSetter[Dynamic[y]], Dynamic[y]}]]

In the examples of WL doc. I often miss, how can I put it, “the other way to use something”.
Too many examples that show the same ‘angle’. I also searched on the internet, but I got the same things as in the WL doc.

If you execute this:

ColorSetter[Dynamic[x]]

then the value of x will be the color displayed by the ColorSetter. If you click on the ColorSetter and change the color it displays, then x will contain the value of the new color. In other words, the answer to your question, “How do I get the vales of the selected color into a variable?” is that you already have the value in a variable–it’s the variable wrapped in Dynamic and passed to the ColorSetter.

The symbol y has the selected color.

{ColorSetter[Dynamic[y]], Dynamic[y]}

Pick a color, then

y // InputForm
(* RGBColor[0.13130388342107271, 0.9996948195620661, 0.023590447852292667] *)

ColorConvert[y, "HSB"] // InputForm
(* Hue[0.3149416123434789, 0.9764023506067313, 0.9996948195620661] *)

Maybe a little more flavor would help. The documentation used the expression

{ColorSetter[Dynamic[x]], Dynamic[x]}

to demonstrate how you can dynamically update a variable with a ColorSetter. That expression isn’t itself the “color setter”. You could just as easily use an expression like this:

NonsenseHead[Dynamic[x], ColorSetter[Dynamic[y]], Dynamic[y], 
 ColorSetter[Dynamic[x]]]

If you evaluate that and play with the output, you can see that one ColorSetter is linked to one dynamic variable and the other to the other.

Eric, I tried, but I get the same result as before, being a little square in the selected color.
If a do :
ColorSetter[Dynamic[x]]
x
I do not get any numbers, I get the colored square.

I need the values of the color, in RGB, Lab and HSB, so for e.g. for Red , something like :

{1,0,0} for RGB
{0.7,50,50} for Lab
{0,0.6,0.8} for HSB

From there on, I can extract the ‘Hue’ or any other parameter for the selected color.

PS. There are two more answeres in the list. One by Rohit Namjoshi and another by you.
They both seem empty to me. Is that correct? I still do not feel very comfortable with how to interact with the Wolfram Forum. Sometimes strange things are manifesting :slight_smile:

Now, just after posting my reply, all of a sudden the content of the two ‘empty’ posts have become visible to me. Bizarre. Sorry for that.

I will read and respond after my dinner.
So ignore my previous post for the moment :slight_smile:

Notice how Rohit applied InputForm to the variable (or maybe you couldn’t see that post). I also like to use FullForm when I want to inspect an expression in detail. Anyway, the little square you’re seeing is just the way a Mathematica notebook renders an RGBColor expression in an output cell. I should have realized that this might be throwing you. It’s extremely common in a Mathematica notebook for the output to be formatted in some “nice” way. If you evaluate Complex[1,1], for example, you’ll see a “nice” representation of that complex number. If you evaluate RGBColor[1,0,0], you’ll see a red box. If you evaluate Rule[a,b], you’ll see an arrow. But if you apply FullForm to each of these, you’ll see that “underneath the covers” they are all just plain old Mathematica expressions with a head and body.

I get it so far. I would never have come up with //FullForm.
This WL really does things different from what I am used to. very surprising.

Now the next step, which I thought I would be able to manage, but I don’t :frowning:

If I select a color, take the //InputForm and convert to HSB I get e.g. the following :

Hue[0.14196606106828644, 0.6012019781875348, 0.9318074311436637]

As this is not a List, I do not know how to extract the parameters separately into the variables ‘h’, ‘s’ and ‘b’.
See my clumsy attempts in the attached Nb :slight_smile:

Okay, let’s break this down into different tasks.

Manipulating and inspecting expressions

Generally, expressions have a head and a body. You can create them on the fly: Abc[1,"alpha",xyz]. If you type that in and evaluate, the output will look just the same, because there are no rewrite rules associated with the symbols, and so nothing gets evaluated/simplfied/rewritten. The head here is Abc and the stuff between the square brackets is the body (but just think of it as more subexpressions).

You can inspect/transform an expression with these functions:

  • Head - tells you the head :). Try it on your variable x when it’s assigned a color value.
  • Part - extracts a subexpression at a location. So, if x = RGBColor[.1,.3,.5], then x[[2]] will give you .3. ([[]] is syntactic sugar for Part).
  • Most, Rest, Take, Drop. Just read the documentation or play with them.
  • FullForm, InputForm, TreeForm, etc. There are several *Form functions. Again, perusing the documentation would be easier than me trying to explain.
  • Apply. This one replaces the head. yadda yadda documentation yadda yadda.

Okay, so to answer your specific question about extracting one element from a Hue expression, the simplest is to use Part:

x = Hue[0.5, 0.6, 0.4];
x[[1]]

This should output .5. You could have assigned that to a new variable, of course.

You also asked about transforming it to a list. For that, you can use Apply:

x = Hue[0.5, 0.6, 0.4];
List @@ x

This should ouput {.5, .6, .4}.

Using Dynamic

Dynamic caused the notebook to automatically display/use the current value of the expression inside it. So, if you evaluate Dynamic[x] and then elsewhere in your notebook play around with x=1, x=2, x=, what should happen is that the ouput cell from where the Dynamic was evaluated will automatically update and display the new value.

ColorSetter

ColorSetter is a special function that creates a color picker widget in the notebook. If you give it a value, then that will be the initial value/color that displays in the color picker widget. Try it with ColorSetter[Green]. Now try it with an undefined symbol, like abc. ColorSetter doesn’t know what to do with such an expression, so it just returns a raw expression. Now try it with abc wrapped in Dynamic: ColorSetter[Dynamic[abc]]. ColorSetter handles Dynamic expressions by setting the value of the wrapped variable. If abc was undefined before you evaluated ColorSetter[Dynamic[abc]], then the value displayed by the color picker widget is the default (Black), and abc will be assigned the value of Black.

Okay, so try this:

  • Restart Mathematica fresh (just a simple way to clean out any
    definitions you might have already).

  • Enter and evaluate this expression:

     ColorSetter[Dynamic[x]]
    
  • In a different cell, enter and evaluate this expression:

     Dynamic[{x, FullForm[x], ColorConvert[x, "HSB"], 
       FullForm[ColorConvert[x, "HSB"]], List @@ ColorConvert[x, "HSB"], 
       ColorConvert[x, "HSB"][[1]]}]
    
  • Now, click on the color picker that was generated by the first input. Choose a color and tap Okay.

If you play around with this, you should start to see how this works. Hopefully one of these expressions will be the one you want (or close enough to get you pointed in the right direction)

Apologies, I forgot to mention…

(* THIS DOES NOT WORK *) h=v[[1]]//InputForm

You had assigned the value to v1, not v. So, v1[[1]] will give you the first part of the expression.

Thanks a lot Eric, fopr your detailed explanation. I will study it tomorrow, but i noticed already that

List@@x works fine.

I really appreciate help like yours, as it is sometimes hard to get one’s fingers behind a certain concept. Once the concept becomes clear, other applications of it will come easier.

I will get back to you tomorrow.

Thanks Eric, your guidance is really helpful. It’s very much appreciated.

I understand what you are explaining to me.
I will look into Apply later, but that seems interesting.

Your code :

Dynamic[{x, FullForm[x], ColorConvert[x, "HSB"], 
  FullForm[ColorConvert[x, "HSB"]], List @@ ColorConvert[x, "HSB"], 
  ColorConvert[x, "HSB"][[1]]}]

Works well and I understand all of it.
So basically, I have now what I want to start with :
The selected color in RGB numbers , as well as in HSB numbers.

Also the List thing works and is understandable.

From here I can continue.

I managed to make use of Apply, I think an important function.
I used it to get the HSB values, which I transformed, again into a ‘color’ format.

hueComp1 stands for a complementary color

colComp1 = Apply[Hue, {hueComp1, orgColorHSBsat, orgColrHSBbrit}]

To show the colors in the form of rectangles I have the following code - with a question :slight_smile:

I don’t understand that not one of the first two lines does work, but only the third way : RGBColor[x]
I have already : orgColorRGB = x // FullForm
So why is it not working as orgColorRGB has the same values as x?

THIS DOES NOT WORK

colorResult1 = Graphics[{RGBColor[orgColorRGB], Rectangle[]}] ;       (*  The ORIGINAL COLOR  *)
colorResult1 = Graphics[{orgColorRGB, Rectangle[]}] ;       (*  The ORIGINAL COLOR  *)

BUT THIS DOES WORK

colorResult1 = Graphics[{RGBColor[x], Rectangle[]}] ;     (*  The ORIGINAL COLOR  *)

I attach the Nb I am working on for reference. The purpose of it is to select a color, and make two complementary colors, with an adjustable speed from the exact complementary color.
I plan to use this to create nice 3 color palettes for my design work.

Thanks again Eric, really helpful.

Best, Beat

Color-2 color complementair §2.nb (9.04 KB)

I seem to have troubles to attach the NoteBook as a seperate file, instead of it being inserted into the post. I managed once, and now I think I do the same, but get different results.

How should I do it correctly?

Hi Cornas,

You can simply attach a notebook to your comment using the button “Add a file to this post” at the bottom of the editor

Thanks. That is the first thing I did and the content of the Nb was somewhere inserted into the Post.
Then I used the btn “Add Notebook” at the left top, that inserted the Nb at the end of my post (possibly because I had my insertion point there.

I just tried and now it worked. I must have messed up somewhere :slight_smile:

The problem is here

orgColorRGB = x // FullForm

In general, form wrappers are not computable expressions, they should be used for display purposes only. Change to

(orgColorRGB = x) // FullForm

Then this will work

colorResult1 = Graphics[{orgColorRGB, Rectangle[]}]

I can see your notebook. Must be some lag or something.

Anyway, later I’ll put together a notebook to show you how I’d approach this. But I’ll put a couple of thoughts here first.

When a result has some sort of error (something recognized by Mathematica as an incorrect usage, not just something that didn’t work the way you expected), there will typically be an associated message. These can show up in a few places:

  • The messages window: in the menu bar, Window → Messages
  • A little red ellipsis near the bracket for the output cell where the error happened
  • If the output itself has a red outline, you can hover over it to see the message

So, for your failed Graphics output, hover over it and you’ll see a message that explains the failure. In your case it is: “FullForm is not a Graphics primitive or directive.” That’s a pretty good clue, and it suggests that the problem is with this line:

orgColorRGB = x // FullForm

So, a quick comment about FullForm and related *Form functions. These are used to inspect data structures. They are helpful for debugging. But they aren’t intended to be part of the data structure (at least I have never done that, and I can’t think of a reason to do so). What you’ve done here is assigned the variable orgColorRGB to FullForm[x], and so if x was RGBColor[0,0,0] then your orgColorRGB is really FullForm[RGBColor[0,0,0]]. Now this data structure will display fine (it should, that’s the purpose of FullForm), but it’s no longer a data structure that is recognized as a color by Graphics. FullForm structures don’t display as FullForm[…], because that would actually be distracting and detract from the usefulness of FullForm. So, if you evaluate FullForm[orgColorRGB], it will just appear like a RGBColor structure in the output. But you can evaluate Head[orgColorRGB] and see that it’s a FullForm.

I think that you are somehow thinking that you need to use FullForm to get at the “numerical represenation” of a color. But you don’t. Just because colors display as little colored squares does not mean that there is some other representation being used. It’s just a display thing. When you use your ColorSetter, you’re setting x to an RGBColor data structure. You don’t need to do anything more to x to use it as a color. You would only apply FullForm to it to see the raw data. FullForm doesn’t actually do any transformation to x itself.

And maybe I’m beating a dead horse, but this isn’t all that mysterious. Every text letter you see on the screen right now, or in any software application, is just a representation of some binary data. That binary data is there, it’s just hidden for our convenience by the various interfaces we use. Mathematica is extending that idea to “higher level” data structures. Evaluate Head[1/2] in one cell and just 1/2 in another cell. Mathematica has a special way to display fractions, but that doesn’t mean that you need to transform 1/2 to some special “numerical form” to use it as a number. Try assigning a variable to FullForm[1/2] and then try to add that variable to 1. Mathematica doesn’t know how to add FullForms to Integers. But of course 1+1/2 will output a new fraction just fine.

On to comment 2: When prototyping something, I’d suggest you work incrementally. Do one step in one input cell and evaluate that. Tweak it until that bit works, and then move on to a new input cell. You have a whole bunch of expressions in one input cell. It makes it difficult to trace the outputs to the inputs. I’ll demonstrate this when I have a moment to put together a demo notebook.

Comment 3: You might still be early in the prototyping stage, so maybe you would have gotten this eventually, but my suggestion is that you bundle up your logic for creating complementary colors into a nice, reusable function. Again, I’ll try to show that later.

Eric, I am gratefull for your patience :slight_smile: This all is very new for me.

I had come across the error messages and sometimes they helped me and sometimes it is like Chinese. I always go to the documentation, but many examples go on about the same aspect of a function or option and do not always make it clear for me.

I understand your explanation about FullForm and it makes sense (of course :slight_smile:
I just wonder, like in this case, if I want to get a new color in the process, by hitting the ColorSetter again, but without losing my original (first) color. That is why I assigned the values of x to a new variable. Hitting the ColorSetter again, would put new values into x.

So to do that, I guess, is to extract the RGB numbers from x and put them into a new variable and stick a new Head on with Apply.
I see the potential of how WL is doing things, but boy, what a different way of thinking with what I am accustomed to :slight_smile:

Comment 2 : I am actually doing that. Maybe not in different cells, but leaving out the semicolons, so I can track the intermediate results and see where I go off the tracks.

Comment 3 : yes, reusable functions are ghreat, but the suit does not fit me too well yet. I am trying to use them where I can.
I am most curious about your way of coding a thing like this.

B.t.w. I made the spread for the two complementary colors with a Dynamic Slider and that works.
Somehow I have chosen to use Dynamic in stead of Manipulate (which I used before), because I have read about some more freedom and possibilities with Dynamic. Unfortunately I can’t remember what exactly it was. Dynamic is harder to get right, unfortunately. But I guess, that eventually I will come up to speed.

best, Beat

Here’s a deeper dive…

Thanks Rohit, this works and let’s me save the values in a seperate variable.

I would never have come up with this solution of putting parentesis.
Something like this, is hard to search in the docs. The only way, I would imagine, to get to a solution is to know and understand the bigger processes behind the scenes, like what exactly is happening when //FullForm is used. Unfortunately, these deeper, but somehow very elementary things are not often mentioned in the docs or for that matter in books. I have read maybe 2500 pages of WL instruction books, but still do not have a clear idea or concept of WL. I fiddle and search until something as by magic starts working. Sometimes just putting a curly bracket in another place does the job, but I feel I still have no clue.

Fortunately there is the forum, populated with very kind and helpful people. Great :slight_smile: