4

In LaTeX one can define colors with the command:

\definecolor{somecolor}{RGB}{0,42,14}

I was wondering if it is possible to obtain the value for the red, green and blue channels for a given color, so something like:

\greenc{somecolor} %result is 42

this can then be used, for instance by PGF/Tikz to perform arithmetic on.

  • Something like \extractcolorspecs from the xcolor package? – user31729 Nov 24 '15 at 16:58
2

Perhaps too much ado for a 'simple' question, but this extracts the floating point values of the color specification.

Improved version:

Rounding the floating point values to integer numbers -- not failsafe of course!

Basic explanation: extractcolorspecs yields the model and color specification in a command, the later giving a CSV list of floating point values, which has to be split. I choose to use expl3 syntax to split this easily and to convert those values into integer numbers.

\documentclass{article}

\usepackage{xcolor}

\definecolor{somecolor}{RGB}{0,42,14}

\usepackage{xparse}

\ExplSyntaxOn
\clist_new:N \l_commusoft_colorchannels_clist
\fp_new:N \l_greenchannel_fp
\fp_new:N \l_bluechannel_fp
\fp_new:N \l_redchannel_fp

\NewDocumentCommand{\SplitColorChannels}{m}{%
\clist_set:Nx \l_commusoft_colorchannels_clist {#1}
}

\NewDocumentCommand{\ExtractColors}{m}{%
\extractcolorspecs{#1}{\mycolormodel}{\mycolor}
\SplitColorChannels{\mycolor}
\fp_set:Nn \l_greenchannel_fp {\clist_item:Nn \l_commusoft_colorchannels_clist {2}}
\fp_set:Nn \l_redchannel_fp {\clist_item:Nn \l_commusoft_colorchannels_clist {1}}
\fp_set:Nn \l_bluechannel_fp {\clist_item:Nn \l_commusoft_colorchannels_clist {3}}
}

\NewDocumentCommand{\ColorRedChannel}{m}{%
\ExtractColors{#1}
\fp_set:Nn \l_tmpa_fp {\fp_eval:n { \l_redchannel_fp * 256}}
\fp_to_int:N \l_tmpa_fp
}

\NewDocumentCommand{\ColorGreenChannel}{m}{%
\ExtractColors{#1}
\fp_set:Nn \l_tmpa_fp {\fp_eval:n { \l_greenchannel_fp * 256}}
\fp_to_int:N \l_tmpa_fp
}

\NewDocumentCommand{\ColorBlueChannel}{m}{%
\ExtractColors{#1}
\fp_set:Nn \l_tmpa_fp {\fp_eval:n { \l_bluechannel_fp * 256}}
\fp_to_int:N \l_tmpa_fp
}


\ExplSyntaxOff
\begin{document}


Red: \ColorRedChannel{somecolor}

Green: \ColorGreenChannel{somecolor}

Blue: \ColorBlueChannel{somecolor}


\end{document}

enter image description here

0

Since you seem to want expandable commands, you have to set the relevant bits at color definition time, because the extraction/conversion functions provided by xcolor are not expandable.

Here's a way, with two “extended” commands for color definition, namely \Xdefinecolor and \Xcolorlet.

\documentclass{article}
\usepackage{xcolor,xparse}

\ExplSyntaxOn
\NewDocumentCommand{\Xdefinecolor}{mmm}
 {
  \definecolor{#1}{#2}{#3}
  \str_if_eq:nnTF { #2 } { RGB }
   { % no conversion necessary
    \tl_set:cx { l_commusoft_#1_red_tl }   { \clist_item:nn { #3 } { 1 } }
    \tl_set:cx { l_commusoft_#1_green_tl } { \clist_item:nn { #3 } { 2 } }
    \tl_set:cx { l_commusoft_#1_blue_tl }  { \clist_item:nn { #3 } { 3 } }
   }
   {
    \convertcolorspec { #2 } { #3 } { RGB } \l_tmpa_clist
    \tl_set:cx { l_commusoft_#1_red_tl }   { \clist_item:Nn \l_tmpa_clist { 1 } }
    \tl_set:cx { l_commusoft_#1_green_tl } { \clist_item:Nn \l_tmpa_clist { 2 } }
    \tl_set:cx { l_commusoft_#1_blue_tl }  { \clist_item:Nn \l_tmpa_clist { 3 } }
   }
 }
\NewDocumentCommand{\Xcolorlet}{mm}
 {
  \colorlet{#1}{#2}
  \commusoft_extractcolorspec:nN {#1} \l_tmpa_tl
  \exp_last_unbraced:Nf \commusoft_convertcolorspec:nnnN \l_tmpa_tl { RGB } \l_tmpa_clist
  \tl_set:cx { l_commusoft_#1_red_tl }   { \clist_item:Nn \l_tmpa_clist { 1 } }
  \tl_set:cx { l_commusoft_#1_green_tl } { \clist_item:Nn \l_tmpa_clist { 2 } }
  \tl_set:cx { l_commusoft_#1_blue_tl }  { \clist_item:Nn \l_tmpa_clist { 3 } }
 }

\DeclareExpandableDocumentCommand{\getred}{m}
 {
  \tl_use:c { l_commusoft_#1_red_tl }
 }
\DeclareExpandableDocumentCommand{\getgreen}{m}
 {
  \tl_use:c { l_commusoft_#1_green_tl }
 }
\DeclareExpandableDocumentCommand{\getblue}{m}
 {
  \tl_use:c { l_commusoft_#1_blue_tl }
 }

\cs_set_eq:NN \commusoft_convertcolorspec:nnnN \convertcolorspec
\cs_set_eq:NN \commusoft_extractcolorspec:nN \extractcolorspec
\ExplSyntaxOff

\Xdefinecolor{somecolor}{RGB}{0,42,14}
\Xdefinecolor{another}{cmyk}{0.2,0.3,0.4,0.5}
\Xcolorlet{tint}{another!20!red}

\begin{document}

\getred{somecolor}, \getgreen{somecolor}, \getblue{somecolor}

\getred{another}, \getgreen{another}, \getblue{another}

\edef\temp{\getred{another}, \getgreen{another}, \getblue{another}}
\texttt{\meaning\temp}

\getred{tint}, \getgreen{tint}, \getblue{tint}

\colorbox{tint}{\qquad}
\colorbox[RGB]{\getred{tint}, \getgreen{tint}, \getblue{tint}}{\qquad}

\colorbox{somecolor}{\qquad}
\colorbox[RGB]{\getred{somecolor}, \getgreen{somecolor}, \getblue{somecolor}}{\qquad}

\end{document}

Notice that in the case of tint, the colors are not the same, due to the flaky conversion from cmyk to RGB (that has less colors available). The \edef shows that the commands are fully expandable.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.