背景
在 MetaPost 中,可以通过调用透明度函数来使颜色变亮或变暗。但是,这允许其他颜色透过,这并不总是理想的。有时应该独立于其透明度来使颜色变亮或变暗,方法是更改其价值。
问题
可以在 MetaPost 中使用乘法来调整颜色,例如:
\definecolor[BaseColour][h=66CEF1]
\startuseMPgraphic{page:ThemeElement}
color baseColour;
baseColour := .5 * \MPcolor{BaseColour};
\stopuseMPgraphic
然而,这改变了饱和,也可能是色调也一样。
问题
在 MetaPost 中,如何控制颜色价值,饱和, 和色调,独立地?
有关的
以下 ConTeXt 代码至少从概念上说明了我想要在 MetaPost 中做的事情:
\definecolor[BaseColour][h=66CEF1]
\definespotcolor[BaseColourSaturation][BaseColour][s=.625]
\definespotcolor[BaseColourValue][BaseColour][value=.625]
\definespotcolor[BaseColourHue][BaseColour][hue=.625]
MetaPost 应用程序手册定义:
SetupColors( auto-SV, shading-SV, grayscale )
来自邮件列表:
看起来,这些函数在 Evince(我正在使用的 PDF 阅读器)中查看时都会呈现相同的输出。
来自手动的你可以采用一个补充因素:
.7[red,white]
例如:
fill unitsquare scaled 1cm withcolor .7[red,white];
但这还不足以提供足够的控制。
答案1
ConTeXt 具有几种颜色转换功能,这些功能内置于核心中:
- CMYK 转灰色
- CMYK 转 RGB
- 灰色到HSV
- HSV 转灰色
- HSV 转 RGB
- RGB 转 CMYK
- RGB 转灰色
- RGB 转 HSV
它们在文件中定义
attr-col.lua
。这里我使用Lua函数
hsvtorgb
将 HSV 输入转换为 MetaPost 可以理解的 RGB 值。界面不太美观,但应该可以帮您入门。您可以随意创建 MetaPost 转换定义。
%% macros=mkvi
\starttexdefinition hsvtorgb #h #s #v
\ctxlua{context("(\letterpercent f, \letterpercent f, \letterpercent f)", attributes.colors.hsvtorgb(#h, #s, #v))}
\stoptexdefinition
\starttext
Hues
\dostepwiserecurse{0}{360}{20}{\dontleavehmode
\startMPcode
fill unitcircle scaled 1cm withcolor \hsvtorgb{\recurselevel}{.76}{.76};
\stopMPcode}
Saturation
\dorecurse{19}{\dontleavehmode
\startMPcode
fill unitcircle scaled 1cm withcolor \hsvtorgb{120}{.04*\recurselevel}{.76};
\stopMPcode}
Value
\dorecurse{19}{\dontleavehmode
\startMPcode
fill unitcircle scaled 1cm withcolor \hsvtorgb{120}{.76}{.04*\recurselevel};
\stopMPcode}
\stoptext
答案2
这是一个允许普通 Metapost 使用 HSV 颜色的解决方案。
prologues := 3;
outputtemplate := "%j%c.eps";
vardef hsv_color(expr h,s,v) =
% following wikipedia article on "HSL and HSV"
save chroma, hh, x, m;
chroma = v*s;
hh = h/60;
x = chroma * (1-abs(hh mod 2 - 1));
m = v - chroma;
if hh < 1: (chroma,x,0)+(m,m,m)
elseif hh < 2: (x,chroma,0)+(m,m,m)
elseif hh < 3: (0,chroma,x)+(m,m,m)
elseif hh < 4: (0,x,chroma)+(m,m,m)
elseif hh < 5: (x,0,chroma)+(m,m,m)
else: (chroma,0,x)+(m,m,m)
fi
enddef;
beginfig(1);
label.rt("Hue", (-12,96));
label.rt("Saturation", (-12,64));
label.rt("Value", (-12,32));
for i=0 upto 18:
fill fullcircle scaled 20 shifted (20i,80) withcolor hsv_color(20i,3/4,3/4);
fill fullcircle scaled 20 shifted (20i,48) withcolor hsv_color(120,i/25,3/4);
fill fullcircle scaled 20 shifted (20i,16) withcolor hsv_color(120,3/4,i/25);
endfor
endfig;
beginfig(2);
for h=10 step 10 until 360:
for s = 0.2 step 0.1 until 1:
fill fullcircle scaled 20 shifted (100s*right) rotated h withcolor hsv_color(h,s,1);
endfor
label(decimal floor(1/2+h), 110 right rotated h);
endfor
endfig;
end.
第一个示例图如下所示:
第二个显示的是色轮v=1
,色轮上的色度沿h
色轮方向变化,越s
靠近中间色度越小。
所有颜色都是平的:明显的渐变(在橙红色区域尤其明显)是一种视觉错觉。