[Tex/LaTex] MetaPost: Adjust colour value (brightness/luminosity)

colorcontextmetaposttransparency

Background

In MetaPost, colours can be lightened or darkened by calling the transparency function. However, this allows other colours to show through, which isn't necessarily desirable all the time. Sometimes a colour should be lightened or darkened independently of its transparency, by changing its value.

Problem

Colours can be adjusted in MetaPost with multiplication, such as:

\definecolor[BaseColour][h=66CEF1]

\startuseMPgraphic{page:ThemeElement}
  color baseColour;
  baseColour := .5 * \MPcolor{BaseColour};
\stopuseMPgraphic

However, that changes the saturation, and possibly the hue as well.

Question

In MetaPost, how do you control a colour's value, saturation, and hue, independently?

Related

The following ConTeXt code illustrates, conceptually at least, what I'd like to do in MetaPost:

\definecolor[BaseColour][h=66CEF1]
\definespotcolor[BaseColourSaturation][BaseColour][s=.625]
\definespotcolor[BaseColourValue][BaseColour][value=.625]
\definespotcolor[BaseColourHue][BaseColour][hue=.625]

The MetaPost Applications manual defines:

SetupColors( auto-SV, shading-SV, grayscale )

From the mailing list:

It appears that these functions all render the same output when viewed in Evince (the PDF reader I am using).

From the manual you can employ a complementary factor:

.7[red,white]

For example:

fill unitsquare scaled 1cm withcolor .7[red,white];

However, this does not provide enough control.

Best Answer

ConTeXt features several colour conversions, which are built into the core:

  • CMYK to grey
  • CMYK to RGB
  • grey to HSV
  • HSV to grey
  • HSV to RGB
  • RGB to CMYK
  • RGB to grey
  • RGB to HSV

They are defined in the file attr-col.lua. Here I use the Lua function hsvtorgb to convert the HSV input to an RGB value which MetaPost understands. The interface is not pretty, but it should get you started. Feel free to create a MetaPost definition for the conversion.

%% macros=mkvi

\starttexdefinition hsvtorgb #h #s #v
  \ctxlua{context("(\letterpercent f, \letterpercent f, \letterpercent f)", attributes.colors.hsvtorgb(#h, #s, #v))}
\stoptexdefinition

\starttext

Hues

\dostepwiserecurse{0}{360}{20}{\dontleavehmode
  \startMPcode
    fill unitcircle scaled 1cm withcolor \hsvtorgb{\recurselevel}{.76}{.76};
  \stopMPcode}

Saturation

\dorecurse{19}{\dontleavehmode
  \startMPcode
    fill unitcircle scaled 1cm withcolor \hsvtorgb{120}{.04*\recurselevel}{.76};
  \stopMPcode}

Value

\dorecurse{19}{\dontleavehmode
  \startMPcode
    fill unitcircle scaled 1cm withcolor \hsvtorgb{120}{.76}{.04*\recurselevel};
  \stopMPcode}

\stoptext

screenshot

Related Question