Message Boards Message Boards

0
|
5999 Views
|
22 Replies
|
0 Total Likes
View groups...
Share
Share this post:

How to extract values from a Color Setter?

Posted 2 years ago

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.

POSTED BY: B. Cornas
22 Replies
Posted 2 years ago

Thanks again, Eric, for your excellent explanations. Some things I got, others are still a bit mysterious for me, as I do not seem to get them working, like the labels. But I will get it eventually.

Lab is another ColorSpace, that is fortunaltely supported by WL. It is a very usefull ColorSpace which I use a lot in working on my photo's and images. It seperates the luminosity (the L channel) from the color, which are in the a (Magenta versus Green) and the b channel (Yellow versus Blue). This is usefull in many ways and Lab is the ColorSpace to get your colors popping and right. Another advantage is, that Lab is constructed to work in the way we humans see. It also tries to be 'linear' in the steps. Channel L goes from 0-100 and the two color channels a & b go from -100 to 100. Any 'color' with zero in both the color channels is so a neutral. Measuring in Lab values makes it easy to detect color casts where they should not be.

Your help was very kind and most usefull. I have put on my heavy duty shoes, as it seems that the road is still quite long :-)

best, Beat

POSTED BY: B. Cornas
Posted 2 years ago

Lists : isn't that what is meant with "Listable"

Yes, exactly. I thought I'd explain it in plain terms rather than force you down another learning trail about attributes.

So this is what overloading means - restricting the input variable to a certain type (Hue).

Overloading basically means having multiple "functions" with the same name. In Java you can overload if your input lists differ in their types. Some languages don't allow overloading at all. In Mathematica, you can overload with pattern matching.

I am probably still thinking Old School [regarding using the color square as input]

Yeah, don't get me wrong. I don't know that I would actually ever do that for real. I was just taking the opportunity to make a point about about representations.

RGB, HSB and Lab triplets above each color. But I suppose I would have to get the numbers the same way as I did in my primitive try, and convert to the different colorSpaces.

Not at all. This bit here,

Flatten[{hue = ColorConvert[rgb, "HSB"], HueSplit[HueComplement[hue], spread]}]

evaluates to a List of Hues. You can apply ToString to them to see them as Hue[0.5, 0.5, 0.5] (or whatever). Before you do the ColorConvert, you'll have RGBColors, and you can apply ToString to those to see RGBColor[0., 0., 0.] (or whatever). I don't know what Lab is, so you might have to come up with your own display representation for that. Or, if you really do want them as just triplets (list of three elements), then do the List@@ thing.

I tried with a different start color for the ColorSetter (not Black), but nothing seemed to work

In the Manipulate, you can change the bit that specifies the controller for rgb to look like this: {{rgb, RGBColor[0.5, 0.22, 0.5]}, ColorSetter}

I am so much used to 'stay' in the numbers and variables, until all the calculations are done and only then do the 'Translation' to the graphics on screen

Right. I pretty much agree with you. That's kind of what I'm trying to explain when I go on about representations. But I think we've reached the limits of being able to communicate this idea within this context, so I won't belabor the point anymore.

POSTED BY: Eric Rimbey
Posted 2 years ago

Eric, you've put quite some work into helping me :-)

The HueComplement function I get. I had something similar, but less general. Lists : isn't that what is meant with "Listable"? Some functions have that attribute, some not.

HueSplit[.99, .07] the Mod nicely wraps the spread around if necessary. Get it.

So this is what overloading means - restricting the input variable to a certain type (Hue).

Eric wrote : Test (Notice how this time I copied the little color square from above directly into this input expression. Mathematica is fine with that.):

I kew this, but it feels very alien to me. I can see that it sometimes might come in handy, but up till now, the opposite has been true for me. But then again, I am probably still thinking Old School :-)

I worked through your excellent example and of course it works, with a much nicer Frame as well :-)

I will need some more time to go nitty gritty on your code and dive again into the docs (Thread and MapAt). Your solution is very elegant.

I noticed that the Dynamic version and the Manipulate version (in one Nb) interfere with each other. probably because of the same Dynamic variable(s).

There is a thing though that I struggle with : I am so much used to 'stay' in the numbers and variables, until all the calculations are done and only then do the 'Translation' to the graphics on screen. F.i. in this case, I would like to add the RGB, HSB and Lab triplets above each color. But I suppose I would have to get the numbers the same way as I did in my primitive try, and convert to the different colorSpaces.

So, I'll get back to you after having studied some more. Thanks

PS. I tried with a different start color for the ColorSetter (not Black), but nothing seemed to work. I guess the wrong syntax, although I tried quite a few.

POSTED BY: B. Cornas
Posted 2 years ago

Here's a deeper dive...

POSTED BY: Eric Rimbey
Posted 2 years ago

Eric, I am gratefull for your patience :-) 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 :-) 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 :-)

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

POSTED BY: B. Cornas
Posted 2 years ago

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.

POSTED BY: Eric Rimbey
Posted 2 years ago

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 :-)

POSTED BY: B. Cornas
Posted 2 years ago

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?

POSTED BY: B. Cornas

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

enter image description here

POSTED BY: Ahmed Elbanna
Posted 2 years ago

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 :-)

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

Attachments:
POSTED BY: B. Cornas
Posted 2 years ago

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[]}]
POSTED BY: Rohit Namjoshi
Posted 2 years ago

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 :-)

POSTED BY: B. Cornas
Posted 2 years ago

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.

POSTED BY: B. Cornas
Posted 2 years ago

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.

POSTED BY: Eric Rimbey
Posted 2 years ago

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=<whatever you want>, 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)

POSTED BY: Eric Rimbey
Posted 2 years ago

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 :-(

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 :-)

POSTED BY: B. Cornas
Posted 2 years ago

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 :-)

POSTED BY: B. Cornas
Posted 2 years ago

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.

POSTED BY: Eric Rimbey
Posted 2 years ago

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] *)
POSTED BY: Rohit Namjoshi
Posted 2 years ago

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.

POSTED BY: Eric Rimbey
Posted 2 years ago

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 :-)

POSTED BY: B. Cornas
Posted 2 years ago

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.

POSTED BY: Eric Rimbey
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract