# 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. –  percusse Jun 9 '12 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. –  Count Zero Jun 9 '12 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... –  Paul Gaborit Jun 9 '12 at 20:01
@PolGab: Ah, yes, you're right, sorry for that! –  Jake Jun 9 '12 at 20:42
Maybe possibly useful in understanding TikZ's interaction with colours: tex.stackexchange.com/a/21542/86 –  Loop Space Jun 9 '12 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. –  Loop Space Jun 9 '12 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. –  Caramdir Jun 9 '12 at 21:45
I use pdftk file.pdf output file-un.pdf uncompress. –  Loop Space Jun 9 '12 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. –  Paul Gaborit Jun 9 '12 at 22:15