cyan 颜色渐变显示不正确

发布于 2021-07-22 15:39:24
\documentclass{standalone}
\usepackage{xcolor}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\fill[cyan!80!white] (2,0) -- (2,4) arc (360:180:2cm and 0.5cm) -- (-2,0) arc (180:360:2cm and 0.5cm);
\fill[cyan] (0,4) circle (2cm and 0.5cm);
\draw[white,line width=2pt] (-2,4) -- (-2,0) arc (180:360:2cm and 0.5cm) -- (2,4) ++ (-2,0) circle (2cm and 0.5cm);
\end{tikzpicture}
\end{document}







\documentclass{standalone}
\usepackage{xcolor}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\draw[white,line width=2pt](0,0) circle (3);
\end{tikzpicture}
\end{document}

两段代码分别画了一个圆柱体和一个球形,圆柱体的两个面分别用cyan 和cyan!80!white,球体设置渐变从cyan到cyan!80!white,可以明显看出两图颜色差别很大,想了解原因是什么,以及如何实现 cyan 的正确渐变

查看更多

关注者
0
被浏览
1.8k
2 个回答
如果您有什么不同意见,您是对的,我是错的。
这家伙很懒,什么也没写!

慕子的回答:

https://github.com/pgf-tikz/pgf/issues/993
\PassOptionsToPackage{cmyk}{xcolor}\PassOptionsToPackage{rgb}{xcolor} 就能看出来了
感觉是 pgf shading 的 bug
相关代码在 https://github.com/pgf-tikz/pgf/blob/afa8dcc67472b70a11bd5f01b3f494243bba9b8a/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex#L345-L365
目前是,默认 rgb,除非指定了 color mode 是 cmyk 或 gray。
但默认情况下,xcolor 使用的 color mode 是 natural。在默认模式下,base colors 的色域,是不同的。而 pdf 要求每个 pattern,包括这里的 shading pattern,只使用单一色域的颜色,所以无法避免色域转换。
大部分 base color,在不同色域下的定义,「看起来」的颜色是相同的,所以转色域后,看起来颜色差异很小。cyan 刚好是例外。
pgf 做得更好的成本有点大,最好还是 henri 说的,让 xcolor 改默认行为。

The main issue here is that xcolor mixes color models without warning.
https://github.com/pgf-tikz/pgf/issues/993#issuecomment-782731021
越来越少
越来越少 2021-07-22
这家伙很懒,什么也没写!
\begin{tikzpicture}
\tikzset{inner color=red,outer color=black}
\pgftext{\pgfuseshading{radial}}
\draw[green,line width=1.2pt](0,0) circle (25bp);
\draw[green,line width=1.2pt](0,0) circle (50bp);
\fill[shading=radial] (5,0) circle (50bp);
\end{tikzpicture}

得到
89342789a0be7f0fbc227ba5ccfdaf61.png
左侧半径为 50bp 的大圆是完整的 radial 渐变。右侧圆中的渐变,就是左侧圆中,半径为 25bp 的那一部分。左侧圆环中的颜色都没有出现在右侧圆中,被裁掉了。

如果想让完整的 radial 渐变出现在右侧圆中,需要重定义 radial 渐变,或者自己另外定义一种渐变。例如重定义 radial 渐变:

\makeatletter
\pgfdeclareradialshading[tikz@radial@inner,tikz@radial@outer]{radial}{\pgfpointorigin}{%
  color(0bp)=(tikz@radial@inner);
  color(25bp)=(tikz@radial@outer)}
\makeatother

这样重定义 radial 渐变的半径为 25bp, 再次绘制前面的圆,得到
1f83e993db1825e14cf5520f32b0c70f.png

其中的详细原因参考 TikZ & PGF Manual 的 114.3 Using Shadings 的命令 \pgfshadepath
——————————————————————————————————————————————
抱歉,以上回答显然是答非所问了,请参考网友 @u33 的回答。
——————————————————————————————————————————————————————————————
转述一下 #993 的要点:

1.在\fill[fill=cyan] (0,0) circle (3);中,颜色 cyan 是 xcolor 宏包预定义的颜色,这个颜色来自 cmyk 模式。
2.在\fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);中,PGF 跟随 xcolor 认定的颜色模式,例子中是 rgb 模式。

cmyk 模式下的颜色 cyan 与 rgb 模式下的 cyan 是不一样的,出现色差。

解决的办法在 #993 中已经给出,即给 xcolor 宏包加上 cmyk 或者 rgb 选项,这是全局设定。

如果想局部设定,可以:

1.重定义颜色 cyan 为 rgb 模式下的颜色。首先获取 rgb 模式下的 cyan 的颜色数据:

\pgfshadecolortorgb{cyan}{\mycol}
\mycolred,\mycolgreen,\mycolblue

就是 0,1,1,然后

\definecolor{cyan}{rgb}{0,1,1}

然后再填充图形。例如:

\begingroup
\definecolor{cyan}{rgb}{0,1,1}
\begin{tikzpicture}
  \fill[fill=cyan] (-7,0) circle (3);
  \fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\end{tikzpicture}
\endgroup

得到
1c1c5ecdb710e13ae17b02bb10335f59.png

2.如果你觉得 cmyk 模式下的颜色 cyan 比较养眼,可以局部的修改 radial 渐变所认定的颜色模式,即修改 \pgf@setup@shading@model 的定义,如下:

\begingroup
\makeatletter
\def\pgf@setup@shading@model{%
  \pgfshadingmodelrgbtrue
  \pgfshadingmodelcmykfalse
  \pgfshadingmodelgrayfalse
  \XC@sdef\pgf@mod@test{\XC@tgt@mod{cmyk}}%修改在这里
  \def\pgf@shading@device{/DeviceRGB}%
  \def\pgf@shading@ps@device{setrgbcolor}%
  \def\pgf@shading@functional@range{0 1 0 1 0 1}%
  \def\pgf@shading@model{rgb}%
  \ifx\pgf@mod@test\XC@mod@cmyk
    \def\pgf@shading@device{/DeviceCMYK}%
    \def\pgf@shading@ps@device{setcmykcolor}%
    \def\pgf@shading@functional@range{0 1 0 1 0 1 0 1}%
    \def\pgf@shading@model{cmyk}%
    \pgfshadingmodelrgbfalse
    \pgfshadingmodelcmyktrue
  \fi
  \ifx\pgf@mod@test\XC@mod@gray
    \def\pgf@shading@device{/DeviceGray}%
    \def\pgf@shading@ps@device{setgray}%
    \def\pgf@shading@functional@range{0 1}%
    \def\pgf@shading@model{gray}%
    \pgfshadingmodelrgbfalse
    \pgfshadingmodelgraytrue
  \fi
  \edef\pgf@sys@driver@dvisvgm{pgfsys-dvisvgm.def}%
  \ifx\pgfsysdriver\pgf@sys@driver@dvisvgm
    \def\pgf@shading@model{rgb}%
  \fi
  \edef\pgf@sys@driver@texforht{pgfsys-tex4ht.def}%
  \ifx\pgfsysdriver\pgf@sys@driver@texforht
    \def\pgf@shading@model{rgb}%
  \fi
}
\makeatother

\begin{tikzpicture}
  \fill[fill=cyan] (-7,0) circle (3);
  \fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\end{tikzpicture}
\endgroup
%重画,做比较
\begin{tikzpicture}
  \fill[fill=cyan] (-7,0) circle (3);
  \fill[inner color=cyan,outer color=cyan!50!white] (0,0) circle (3);
\end{tikzpicture}

得到
44b5f6228538af60b84354985ee01984.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览