Skip to main content

color - Create colour with given lightness value



How can I create a colour of my chosen hue with a given fixed lightness level?


For example, how can I create a reddish colour, col, so that ColorConvert[col, "GrayScale"] will return precisely GrayLevel[0.6]?


Does Mathematica have something built-in to assist in this, or do I need to read up on how colours are converted between various representations? Note that the b value in Hue[h, s, b] does not correspond to the GrayLevel value. I need to have precise control over what certain colours I use will look like when converted to greyscale.



Answer



Conversion Formula


ColorConvert uses the following formula for "Grayscale" conversion:


$ \mathrm{Grayscale} = 0.299 R + 0.587 G + 0.114 B$


where $R$, $G$, and $B$ are normalized.


Interactive Example


The following manipulate example will help you finding (and confirming) the conversion based on a fixed $\mathrm{Grayscale}$ and $R$ values.



f[g_, gs_, r_] := (gs - .299 r - .587 g)/.114;

Manipulate[
Column[{
Show[
Graphics[{Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}},
VertexColors -> {RGBColor[r, 0, 0], RGBColor[r, 1, 0],
RGBColor[r, 1, 1], RGBColor[r, 0, 1]}]},
PlotRange -> {{0, 1}, {0, 1}}, PlotRangeClipping -> True,
AspectRatio -> 1,

ImageSize -> 400,
Frame -> True, FrameLabel -> {"Green", "Blue"},
LabelStyle -> {FontFamily -> "Arial", FontSize -> 14}],
Plot[f[g, gs, r], {g, 0, 1}],
Graphics[{
Locator[
Dynamic[pt, (With[{b = f[#[[1]], gs, r]},
If[0 <= b <= 1, pt = {#1[[1]], b}, {.5, .5}]]) &]]
}]
],

"",
Row[{"ColorConvert[RGBColor[", Prepend[pt, r],
",\"Grayscale\"]==\n",
ColorConvert[RGBColor[Prepend[pt, r]], "Grayscale"]}]
}],
{{pt, {.5, .5}}, ControlType -> None},
{{gs, .5, "Grayscale"}, 0, 1, Appearance -> "Labeled"},
{{r, 1, "Red"}, 0, 1, Appearance -> "Labeled"},
SaveDefinitions -> True]


grayscale


The blue line indicates the colors which has the exact grayscale value. If you move the locator, it tries to snap in to the line and show you RGB value as well as converted graysale value (which should be the same as the slider value).


Discussion


belisarius asked, "Then what is the yellowest color whose grayscale value is .3?".


There are several problems. First, what is "yellow"-ish colors? Are these colors close to {1,1,0} in RGB space? Then the solution is the point on the plane 0.299 x + 0.587 y + 0.114 z = 0.3 whose distance is the shortest from {1,1,0} which can be easily solvable. But you will quickly realize that it is not really "yellow". For instance, {1,0,0} and {0,1,0} are both exactly the same distance from the yellow, but none perceive them as yellowish. Then, is it a point with the proportion of R and G is 1:1? It is better but not entirely. Red and green have difference luminescence (thus different weights in grayscale conversion). Now, should we consider the weight? Well, then how about gamma and gamut? Then Euclidean distance becomes useless... I wouldn't even start the fact that human color perception is not linear but more of quadratic space... And then there is a whole story about chromaticity and visible spectrum (then different "yellow" there).


Getting the closest color for some color can be surprisingly hard.


Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

How to thread a list

I have data in format data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}} Tableform: I want to thread it to : tdata = {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} Tableform: And I would like to do better then pseudofunction[n_] := Transpose[{data2[[1]], data2[[n]]}]; SetAttributes[pseudofunction, Listable]; Range[2, 4] // pseudofunction Here is my benchmark data, where data3 is normal sample of real data. data3 = Drop[ExcelWorkBook[[Column1 ;; Column4]], None, 1]; data2 = {a #, b #, c #, d #} & /@ Range[1, 10^5]; data = RandomReal[{0, 1}, {10^6, 4}]; Here is my benchmark code kptnw[list_] := Transpose[{Table[First@#, {Length@# - 1}], Rest@#}, {3, 1, 2}] &@list kptnw2[list_] := Transpose[{ConstantArray[First@#, Length@# - 1], Rest@#}, {3, 1, 2}] &@list OleksandrR[list_] := Flatten[Outer[List, List@First[list], Rest[list], 1], {{2}, {1, 4}}] paradox2[list_] := Partition[Riffle[list[[1]], #], 2] & /@ Drop[list, 1] RM[list_] := FoldList[Transpose[{First@li...

front end - keyboard shortcut to invoke Insert new matrix

I frequently need to type in some matrices, and the menu command Insert > Table/Matrix > New... allows matrices with lines drawn between columns and rows, which is very helpful. I would like to make a keyboard shortcut for it, but cannot find the relevant frontend token command (4209405) for it. Since the FullForm[] and InputForm[] of matrices with lines drawn between rows and columns is the same as those without lines, it's hard to do this via 3rd party system-wide text expanders (e.g. autohotkey or atext on mac). How does one assign a keyboard shortcut for the menu item Insert > Table/Matrix > New... , preferably using only mathematica? Thanks! Answer In the MenuSetup.tr (for linux located in the $InstallationDirectory/SystemFiles/FrontEnd/TextResources/X/ directory), I changed the line MenuItem["&New...", "CreateGridBoxDialog"] to read MenuItem["&New...", "CreateGridBoxDialog", MenuKey["m", Modifiers-...