# How to make correct shading with hsb color model?

I want to use hsb color model to shading.

First rectangle shows a shading using rgb color model.

Second rectangle shows a shading using hsb color model. But I don't understand why I don't obtain the same shading that with my third rectangle.

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
% create some hsb colors
\colorlet{redhsb}[hsb]{red}%
\colorlet{bluehsb}[hsb]{blue}%
\colorlet{greenhsb}[hsb]{green}%

% first shading with rgb color model
\fill[left color=red,right color=blue] (0,1) rectangle (2,0);

% second shading with hsb color model
\fill[left color=redhsb,right color=bluehsb] (0,0) rectangle (2,-1);

% third shading with hsb color model
\fill[left color=redhsb,right color=greenhsb] (0,-1) rectangle (1,-2);
\fill[left color=greenhsb,right color=bluehsb] (1,-1) rectangle (2,-2);
\end{tikzpicture}
\end{document}


Edit: In fact, TikZ calculates the middle color (using color model of the left color). Then, it converts all three colors to rgb model and make shading...

% fourth shading with rgb color model
\fill[left color=red,right color=green] (0,-2) rectangle ++(1,-1);
\fill[left color=green,right color=blue] (1,-2) rectangle ++(1,-1);


So, my question is: Can TikZ do real hsb (HSV) shading?

• I think this because there is no straight path from red to blue as in your third rectangle shows. I'm not very informed about the subject but an hsv interpolation for a->b is not the same as for a->c->b. You can test this by only making your second and third colors rgb again. Commented Jun 9, 2012 at 17:52
• I have the same suspicion: the RGB coordinates provide a 'straight path' from red to blue (simply decrease value of R, increase value of B - linearly). In the case of HSV (or HSL for that matter) on the contrary, the transition from red to blue is by changing the hue parameter, which is an angle in cylindrical coordinates. By linearly changing it, you must pass through other colors. The difference between the bottom pictures has probably to do with the way tikz maps HSL to RGB. Commented Jun 9, 2012 at 19:38
• @CountZero Your last sentence gives me a clue... To make shading, TikZ calculates the middle color (using color model of the left color). Then, it converts all three colors to rgb model to make shading... Commented Jun 9, 2012 at 20:01
• @PolGab: Ah, yes, you're right, sorry for that!
– Jake
Commented Jun 9, 2012 at 20:42
• Maybe possibly useful in understanding TikZ's interaction with colours: tex.stackexchange.com/a/21542/86 Commented Jun 9, 2012 at 21:05

The following happens when you do \fill[left color=redhsb,right color=bluehsb] (0,0) rectangle (2,-1);

• TikZ sets three internal colors:

• tikz@axis@bottom=bluehsb
• tikz@axis@middle=redhsb!50!bluehsb
• tikz@axis@top=redhsb

The middle color is calculated by xcolor, which does the mixing in the first color model (HSB in this case).

• TikZ uses a shading declared by

\pgfdeclareverticalshading[tikz@axis@top,tikz@axis@middle,tikz@axis@bottom]{axis}{100bp}{%
color(0bp)=(tikz@axis@bottom);
color(25bp)=(tikz@axis@bottom);
color(50bp)=(tikz@axis@middle);
color(75bp)=(tikz@axis@top);
color(100bp)=(tikz@axis@top)}

• pgf basically passes this through to \pgfsys@vertshading.

• The definition of this command depends on the output driver. For PDF it is

\def\pgfsys@vertshading#1#2#3{%
{%
\pgf@parsefunc{#3}%
\pgfmathparse{#2}%
\setbox\pgfutil@tempboxa=\hbox to\pgfmathresult pt{\vbox to\pgf@max{\vfil\pgfsys@invoke{/Sh sh}}\hfil}%
\pgf@process{\pgfpoint{#2}{\pgf@max}}%
\pdfxform resources {%
/ColorSpace /DeviceRGB
/Domain [\pgf@pdfparseddomain]
/Coords [0 \pgf@doma\space0 \pgf@domb]
/Function \pgf@pdfparsedfunction
/Extend [false false] >> >>}\pgfutil@tempboxa% <<
}%
}


I won't pretend to understand everything that is going on, but as far as I can tell, pgf only writes the 3 computed colors and tells the PDF-viewer to do the shading by linear interpolation. In other words, TikZ doesn't seem to do the shading calculations itself.

As you see above, the color space is set to DeviceRGB. Indeed I think that PDF doesn't support HSL (though I haven't checked to PDF documentation).

As far as I understand, the only way to get HSL interpolation is to write a PostScript shader that does the interpolation and then converts the result to RGB.

• I have just checked the PDF documentation (or at least, Adobe's copy of it at adobe.com/devnet/pdf/pdf_reference.html) and HSL is not supported. Table 62 on p139 lists DeviceGray, DeviceRGB, DeviceCMYK. Commented Jun 9, 2012 at 21:24
• Btw, j-b.livejournal.com/339214.html is very useful if one wants to see what is contained in a PDF file. Commented Jun 9, 2012 at 21:45
• I use pdftk file.pdf output file-un.pdf uncompress. Commented Jun 9, 2012 at 21:52
• Thank you for your analysis. I suspected something like that but interactions between tikz, basic layer and system layer of pgf are often difficult to understand. Commented Jun 9, 2012 at 22:15