[Tex/LaTex] Why does xcolor lighten a color when mixed

colortikz-pgf

I'm trying to create a smooth gradient between cyan and blue connecting two shapes, one drawn in cyan and one in blue.
For that I use a simple mix of the two colors in a \foreach loop.

However, in the first step of the mix, despite having only 0.5% blue mixed with (presumably) 99.5% cyan, the resulting color differs drastically from pure cyan.

What am I missing and how can the effect be properly achieved?
To be clear: what colors and in what ratios should be mixed to achieve the first step from pure cyan towards pure blue?

MWE:

\documentclass[tikz]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
    \draw[cyan,fill=cyan] (0,0) rectangle (1,1);
    \draw[blue!0.5!cyan,fill=blue!0.5!cyan] (1,0) rectangle (2,1);
\end{tikzpicture}
\end{document}

and the output:

color mix example

Here is the problem presented while using \shade:

\documentclass[tikz]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
  \shade[left color=blue,right color=cyan] (0,0) rectangle (2,1);
  \draw[cyan,fill=cyan] (2,0) rectangle (3,1);
\end{tikzpicture}
\end{document}

and the result:

problem when using shade

The problem was solved by @PaulGaborit and @percusse as can be seen in the comments below by setting:

\colorlet{cyan}[rgb]{cyan}

If I understand correctly, xcolor decides what color scheme to use (rgb/cym) according to the default scheme of the first color in the mix, and uses the predefined name of the second color (in this case 'cyan') under the first color's scheme. Therefore, when using basic colors from differing schemes, the higher boundary of the mix (when the second color is dominant) may differ from the default, 'pure' color.

Section 2.3.2 on page 15 of the xcolor manual (V2.11) kind of suggests that this is what happens, in retrospect.

Best Answer

The xcolor package defines blue as a RGB color and cyan as a CMY color.

To make a mix, xcolor uses the color model of the first color and, if necessary, converts the second color.

To convert the CMY cyan to RGB cyan, you may add \colorlet{cyan}[rgb]{cyan} in your preamble.

\documentclass[tikz]{standalone}
\usepackage{tikz}
\colorlet{cyan}[rgb]{cyan}
\begin{document}
\begin{tikzpicture}
    \draw[cyan,fill=cyan] (0,0) rectangle (1,1);
    \draw[blue!0.5!cyan,fill=blue!0.5!cyan] (1,0) rectangle (2,1);
\end{tikzpicture}
\end{document}

Extract from xcolor manual (section 2.3.2 "Meaning of standard color expressions", p. 15, v2.11):

In general, the second color is transformed into the model of the first color then the mix is calculated within that model. Thus, name1!<percent>!name2 and name2!<100-percent>!name1 which should be equivalent theoretically, will not necessarily yield identical visual results.

Here is an example with three rows: default models, pure rgb model and pure cmy model.

enter image description here

\documentclass[tikz,margin=1mm]{standalone}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{positioning}

\colorlet{cmycyan}{cyan}
\colorlet{rgbcyan}[rgb]{cyan}

\colorlet{cmyblue}[cmy]{blue}
\colorlet{rgbblue}{blue}

\begin{document}
\begin{tikzpicture}
  \tikzset{
    block/.style 2 args={
      draw,right=-.5\pgflinewidth of a,
      fill=#1,text=#2,
      text height=.8em,text depth=.2em,text width=3.5cm,
      font=\ttfamily\bfseries,align=center,
    },
  }
  \node[anchor=base east] (a) {default models};
  \foreach \col/\txtcol in {blue/white,blue!1!cyan/black,cyan!99!blue/white,cyan/white}{
    \node[block={\col}{\txtcol}](a){\col};
  }

  \node[anchor=base east] (a) at (0,-1) {rgb model};
  \foreach \col/\txtcol in {rgbblue/white,rgbblue!1!rgbcyan/black,rgbcyan!99!rgbblue/black,rgbcyan/black}{
    \node[block={\col}{\txtcol}](a){\col};
  }

  \node[anchor=base east] (a) at (0,-2) {cmy model};
  \foreach \col/\txtcol in {cmyblue/white,cmyblue!1!cmycyan/white,cmycyan!99!cmyblue/white,cmycyan/white}{
    \node[block={\col}{\txtcol}](a){\col};
  }
\end{tikzpicture}
\end{document}
Related Question