我有一些生成餅圖圖像的代碼。這是一個通用的類,所以可以給出任意數量的切片作爲輸入。現在我有問題爲切片挑選好顏色。是否有一些算法擅長?如何爲餅圖選擇顏色?
或者我應該手工挑選並列出固定顏色?但是有多少。也許10種顏色,希望有沒有超過10片有史以來?另外,要挑選哪10種顏色?
顏色需要遵循一些規則:
- 他們需要好看
- 相鄰顏色不應該是相似的(藍色旁邊的綠色是一個不走)
- 派背景顏色爲白色,所以白色是不可選的
某些算法與RGB值操作將是一個首選的解決方案。
我有一些生成餅圖圖像的代碼。這是一個通用的類,所以可以給出任意數量的切片作爲輸入。現在我有問題爲切片挑選好顏色。是否有一些算法擅長?如何爲餅圖選擇顏色?
或者我應該手工挑選並列出固定顏色?但是有多少。也許10種顏色,希望有沒有超過10片有史以來?另外,要挑選哪10種顏色?
顏色需要遵循一些規則:
某些算法與RGB值操作將是一個首選的解決方案。
我會預編譯一個約20種顏色的列表,然後開始重複使用第二個顏色。這樣你就不會破壞你的第二條規則。另外,如果有人制作了超過20片的餅圖,它們的問題就更大了。 :)
這正是我目前正在從事的Web應用程序所做的。創建20個,然後重複這20次,創建200個列表。但是,我有一個包含20多個切片的餅圖,顏色正在重複。有什麼建議麼? – 2009-02-06 20:40:51
如果您真的需要〜200種不同的顏色,您可能需要考慮使用Web安全調色板(或子集)。 http://en.wikipedia.org/wiki/Web_colors – 2009-02-06 21:15:25
我發現這個僞代碼公式可能有幫助。你可以從一個集合開始播種。
色差公式
以下是由W3C推薦,以確定兩種顏色之間的差的公式。 (綠色值1,綠色值2) - 最小值(紅色值1,紅色值2)) - )+(最大(藍色值1,藍值2) - 最小(藍色值1,藍值2))
的背景顏色和前景顏色之間的差應大於500
有一個發電機here。它適用於網頁設計,但顏色在餅圖上看起來也很棒。
您可以預先編譯好的顏色列表,也可以檢查生成器背後的邏輯並自己做類似的事情。
看一看Color Brewer,這個工具可以幫助定義一個着色方案來傳達定性或定量信息:地圖,圖表等。這個工具可以生成三種「類型」的調色板 - 順序,定性,和發散 - 你可能需要後者,發散...
你甚至可以下載所有調色板的RGB定義的Excel文件。
我解決它,如下所示:
baseHue
)。hue = baseHue + ((240/pieces) * piece % 240
在C#:
int n = 12;
Color baseColor = System.Drawing.ColorTranslator.FromHtml("#8A56E2");
double baseHue = (new HSLColor(baseColor)).Hue;
List<Color> colors = new List<Color>();
colors.Add(baseColor);
double step = (240.0/(double)n);
for (int i = 1; i < n; ++i)
{
HSLColor nextColor = new HSLColor(baseColor);
nextColor.Hue = (baseHue + step * ((double)i)) % 240.0;
colors.Add((Color)nextColor);
}
string colors = string.Join(",", colors.Select(e => e.Name.Substring(2)).ToArray());
的使用12件和#8A56E2基色Google Charts example:
這1985紙由「ROSS E.羅利,CAPT」給出對於任意組最大化分色的算法的顏色(complete with code in FORTRAN)。如果你想堅持到了一套20種顏色,一個快速和簡單的解決辦法
(分色似乎是一個重要的可視化問題,爲軍隊,以防止藍上藍的事件。)
然而選擇十二面體的頂點並將(x,y,z)座標(適當縮放)轉換爲(r,g,b)。
建立在this solution的基礎上來解決問題的規則#2,下面的算法在餅圖的中點交換顏色。這兩個參數:
我使用ColorHSL,ColorRGB和ColorUtils(下面提供)。
public static function ColorArrayGenerator(
pNbColors:int,
pNonAdjacentSimilarColor:Boolean = false):Array
{
var colors:Array = new Array();
var baseRGB:ColorRGB = new ColorRGB();
baseRGB.setRGBFromUint(0x8A56E2);
var baseHSL:ColorHSL = new ColorHSL();
rgbToHsl(baseHSL, baseRGB);
var currentHue:Number = baseHSL.Hue;
colors.push(baseRGB.getUintFromRGB());
var step:Number = (360.0/pNbColors);
var nextHSL:ColorHSL;
var nextRGB:ColorRGB;
var i:int;
for (i = 1; i < pNbColors; i++)
{
currentHue += step;
if (currentHue > 360)
{
currentHue -= 360;
}
nextHSL = new ColorHSL(currentHue, baseHSL.Saturation, aseHSL.Luminance);
nextRGB = new ColorRGB();
hslToRgb(nextRGB, nextHSL);
colors.push(nextRGB.getUintFromRGB());
}
if (pNonAdjacentSimilarColor == true &&
pNbColors > 2)
{
var holder:uint = 0;
var j:int;
for (i = 0, j = pNbColors/2; i < pNbColors/2; i += 2, j += 2)
{
holder = colors[i];
colors[i] = colors[j];
colors[j] = holder;
}
}
return colors;
}
這產生了右手側輸出:
ColorHSL類:
final public class ColorHSL
{
private var _hue:Number; // 0.0 .. 359.99999
private var _sat:Number; // 0.0 .. 100.0
private var _lum:Number; // 0.0 .. 100.0
public function ColorHSL(
hue:Number = 0,
sat:Number = 0,
lum:Number = 0)
{
_hue = hue;
_sat = sat;
_lum = lum;
}
[Bindable]public function get Hue():Number
{
return _hue;
}
public function set Hue(value:Number):void
{
if (value > 360)
{
_hue = value % 360;
} // remember, hue is modulo 360
else if (value < 0)
{
_hue = 0;
}
else
{
_hue = value;
}
}
[Bindable]public function get Saturation():Number
{
return _sat;
}
public function set Saturation(value:Number):void
{
if (value > 100.0)
{
_sat = 100.0;
}
else if (value < 0)
{
_sat = 0;
}
else
{
_sat = value;
}
}
[Bindable]public function get Luminance():Number
{
return _lum;
}
public function set Luminance(value:Number):void
{
if (value > 100.0)
{
_lum = 100.0;
}
else if (value < 0)
{
_lum = 0;
}
else
{
_lum = value;
}
}
}
ColorRGB類:
final public class ColorRGB
{
private var _red:uint;
private var _grn:uint;
private var _blu:uint;
private var _rgb:uint; // composite form: 0xRRGGBB or #RRGGBB
public function ColorRGB(red:uint = 0, grn:uint = 0, blu:uint = 0)
{
setRGB(red, grn, blu);
}
[Bindable]public function get red():uint
{
return _red;
}
public function set red(value:uint):void
{
_red = (value & 0xFF);
updateRGB();
}
[Bindable]public function get grn():uint
{
return _grn;
}
public function set grn(value:uint):void
{
_grn = (value & 0xFF);
updateRGB();
}
[Bindable]public function get blu():uint
{
return _blu;
}
public function set blu(value:uint):void
{
_blu = (value & 0xFF);
updateRGB();
}
[Bindable]public function get rgb():uint
{
return _rgb;
}
public function set rgb(value:uint):void
{
_rgb = value;
_red = (value >> 16) & 0xFF;
_grn = (value >> 8) & 0xFF;
_blu = value & 0xFF;
}
public function setRGB(red:uint, grn:uint, blu:uint):void
{
this.red = red;
this.grn = grn;
this.blu = blu;
}
public function setRGBFromUint(pValue:uint):void
{
setRGB(((pValue >> 16) & 0xFF), ((pValue >> 8) & 0xFF), (pValue & 0xFF));
}
public function getUintFromRGB():uint
{
return ((red << 16) | (grn << 8) | blu);
}
private function updateRGB():void
{
_rgb = (_red << 16) + (_grn << 8) + blu;
}
}
ColorUtils類:
final public class ColorUtils
{
public static function HSV2RGB(hue:Number, sat:Number, val:Number):uint
{
var red:Number = 0;
var grn:Number = 0;
var blu:Number = 0;
var i:Number;
var f:Number;
var p:Number;
var q:Number;
var t:Number;
hue%=360;
sat/=100;
val/=100;
hue/=60;
i = Math.floor(hue);
f = hue-i;
p = val*(1-sat);
q = val*(1-(sat*f));
t = val*(1-(sat*(1-f)));
if (i==0)
{
red=val;
grn=t;
blu=p;
}
else if (i==1)
{
red=q;
grn=val;
blu=p;
}
else if (i==2)
{
red=p;
grn=val;
blu=t;
}
else if (i==3)
{
red=p;
grn=q;
blu=val;
}
else if (i==4)
{
red=t;
grn=p;
blu=val;
}
else if (i==5)
{
red=val;
grn=p;
blu=q;
}
red = Math.floor(red*255);
grn = Math.floor(grn*255);
blu = Math.floor(blu*255);
return (red<<16) | (grn << 8) | (blu);
}
//
public static function RGB2HSV(pColor:uint):Object
{
var red:uint = (pColor >> 16) & 0xff;
var grn:uint = (pColor >> 8) & 0xff;
var blu:uint = pColor & 0xff;
var x:Number;
var val:Number;
var f:Number;
var i:Number;
var hue:Number;
var sat:Number;
red/=255;
grn/=255;
blu/=255;
x = Math.min(Math.min(red, grn), blu);
val = Math.max(Math.max(red, grn), blu);
if (x==val){
return({h:undefined, s:0, v:val*100});
}
f = (red == x) ? grn-blu : ((grn == x) ? blu-red : red-grn);
i = (red == x) ? 3 : ((grn == x) ? 5 : 1);
hue = Math.floor((i-f/(val-x))*60)%360;
sat = Math.floor(((val-x)/val)*100);
val = Math.floor(val*100);
return({h:hue, s:sat, v:val});
}
/**
* Generates an array of pNbColors colors (uint)
* The colors are generated to fill a pie chart (meaning that they circle back to the starting color)
* @param pNbColors The number of colors to generate (ex: Number of slices in the pie chart)
* @param pNonAdjacentSimilarColor Should the colors stay Adjacent or not ?
*/
public static function ColorArrayGenerator(
pNbColors:int,
pNonAdjacentSimilarColor:Boolean = false):Array
{
// Based on http://www.flexspectrum.com/?p=10
var colors:Array = [];
var baseRGB:ColorRGB = new ColorRGB();
baseRGB.setRGBFromUint(0x8A56E2);
var baseHSL:ColorHSL = new ColorHSL();
rgbToHsl(baseHSL, baseRGB);
var currentHue:Number = baseHSL.Hue;
colors.push(baseRGB.getUintFromRGB());
var step:Number = (360.0/pNbColors);
var nextHSL:ColorHSL;
var nextRGB:ColorRGB;
var i:int;
for (i = 1; i < pNbColors; i++)
{
currentHue += step;
if (currentHue > 360)
{
currentHue -= 360;
}
nextHSL = new ColorHSL(currentHue, baseHSL.Saturation, baseHSL.Luminance);
nextRGB = new ColorRGB();
hslToRgb(nextRGB, nextHSL);
colors.push(nextRGB.getUintFromRGB());
}
if (pNonAdjacentSimilarColor == true &&
pNbColors > 2)
{
var holder:uint = 0;
var j:int;
for (i = 0, j = pNbColors/2; i < pNbColors/2; i += 2, j += 2)
{
holder = colors[i];
colors[i] = colors[j];
colors[j] = holder;
}
}
return colors;
}
static public function rgbToHsl(hsl:ColorHSL, rgb:ColorRGB):void
{
var h:Number = 0;
var s:Number = 0;
var l:Number = 0;
// Normalizes incoming RGB values.
//
var dRed:Number = (Number)(rgb.red/255.0);
var dGrn:Number = (Number)(rgb.grn/255.0);
var dBlu:Number = (Number)(rgb.blu/255.0);
var dMax:Number = Math.max(dRed, Math.max(dGrn, dBlu));
var dMin:Number = Math.min(dRed, Math.min(dGrn, dBlu));
//-------------------------
// hue
//
if (dMax == dMin)
{
h = 0; // undefined
}
else if (dMax == dRed && dGrn >= dBlu)
{
h = 60.0 * (dGrn - dBlu)/(dMax - dMin);
}
else if (dMax == dRed && dGrn < dBlu)
{
h = 60.0 * (dGrn - dBlu)/(dMax - dMin) + 360.0;
}
else if (dMax == dGrn)
{
h = 60.0 * (dBlu - dRed)/(dMax-dMin) + 120.0;
}
else if (dMax == dBlu)
{
h = 60.0 * (dRed - dGrn)/(dMax - dMin) + 240.0;
}
//-------------------------
// luminance
//
l = (dMax + dMin)/2.0;
//-------------------------
// saturation
//
if (l == 0 || dMax == dMin)
{
s = 0;
}
else if (0 < l && l <= 0.5)
{
s = (dMax - dMin)/(dMax + dMin);
}
else if (l>0.5)
{
s = (dMax - dMin)/(2 - (dMax + dMin)); //(dMax-dMin > 0)?
}
hsl.Hue = h;
hsl.Luminance = l;
hsl.Saturation = s;
} // rgbToHsl
//---------------------------------------
// Convert the input RGB values to the corresponding HSL values.
//
static public function hslToRgb(rgb:ColorRGB, hsl:ColorHSL):void
{
if (hsl.Saturation == 0)
{
// Achromatic color case, luminance only.
//
var lumScaled:int = (int)(hsl.Luminance * 255.0);
rgb.setRGB(lumScaled, lumScaled, lumScaled);
return;
}
// Chromatic case...
//
var dQ:Number = (hsl.Luminance < 0.5) ? (hsl.Luminance * (1.0 + hsl.Saturation)): ((hsl.Luminance + hsl.Saturation) - (hsl.Luminance * hsl.Saturation));
var dP:Number = (2.0 * hsl.Luminance) - dQ;
var dHueAng:Number = hsl.Hue/360.0;
var dFactor:Number = 1.0/3.0;
var adT:Array = [];
adT[0] = dHueAng + dFactor; // Tr
adT[1] = dHueAng; // Tg
adT[2] = dHueAng - dFactor; // Tb
for (var i:int = 0; i < 3; i++)
{
if (adT[i] < 0)
{
adT[i] += 1.0;
}
if (adT[i] > 1)
{
adT[i] -= 1.0;
}
if ((adT[i] * 6) < 1)
{
adT[i] = dP + ((dQ - dP) * 6.0 * adT[i]);
}
else if ((adT[i] * 2.0) < 1) // (1.0/6.0) <= adT[i] && adT[i] < 0.5
{
adT[i] = dQ;
}
else if ((adT[i] * 3.0) < 2) // 0.5 <= adT[i] && adT[i] < (2.0/3.0)
{
adT[i] = dP + (dQ-dP) * ((2.0/3.0) - adT[i]) * 6.0;
}
else
{
adT[i] = dP;
}
}
rgb.setRGB(adT[0] * 255.0, adT[1] * 255.0, adT[2] * 255.0);
} // hslToRgb
//---------------------------------------
// Adjust the luminance value by the specified factor.
//
static public function adjustRgbLuminance(rgb:ColorRGB, factor:Number):void
{
var hsl:ColorHSL = new ColorHSL();
rgbToHsl(hsl, rgb);
hsl.Luminance *= factor;
if (hsl.Luminance < 0.0)
{
hsl.Luminance = 0.0;
}
if (hsl.Luminance > 1.0)
{
hsl.Luminance = 1.0;
}
hslToRgb(rgb, hsl);
}
//---------------------------------------
//
static public function uintTo2DigitHex(value:uint):String
{
var str:String = value.toString(16).toUpperCase();
if (1 == str.length)
{
str = "0" + str;
}
return str;
}
//---------------------------------------
//
static public function uintTo6DigitHex(value:uint):String
{
var str:String = value.toString(16).toUpperCase();
if (1 == str.length) {return "00000" + str;}
if (2 == str.length) {return "0000" + str;}
if (3 == str.length) {return "000" + str;}
if (4 == str.length) {return "00" + str;}
if (5 == str.length) {return "0" + str;}
return str;
}
}
從RGB轉換爲HSV,然後調整色相(如answered here)創建一個不一致的感知的亮度。將黃色/綠色明顯比藍色淡/紫色:
沒有這種變化類似的結果是可能的:
的算法,然而,要複雜得多:
(360.0 div $wedges) * $wedge
這裏的RGB值是在XSLT 1.0示例實現方式:
<?xml version="1.0"?>
<!--
| The MIT License
|
| Copyright 2014 White Magic Software, Inc.
|
| Permission is hereby granted, free of charge, to any person
| obtaining a copy of this software and associated documentation
| files (the "Software"), to deal in the Software without
| restriction, including without limitation the rights to use,
| copy, modify, merge, publish, distribute, sublicense, and/or
| sell copies of the Software, and to permit persons to whom the
| Software is furnished to do so, subject to the following
| conditions:
|
| The above copyright notice and this permission notice shall be
| included in all copies or substantial portions of the Software.
|
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
| OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
| WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
| OTHER DEALINGS IN THE SOFTWARE.
+-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Reference white (X, Y, and Z components) -->
<xsl:variable name="X_r" select="0.950456"/>
<xsl:variable name="Y_r" select="1.000000"/>
<xsl:variable name="Z_r" select="1.088754"/>
<xsl:variable name="LAB_EPSILON" select="216.0 div 24389.0"/>
<xsl:variable name="LAB_K" select="24389.0 div 27.0"/>
<!-- Pie wedge colours based on this hue. -->
<xsl:variable name="base_colour" select="'46A5E5'"/>
<!-- Pie wedge stroke colour. -->
<xsl:variable name="stroke_colour" select="'white'"/>
<!--
| Creates a colour for a particular pie wedge.
|
| http://en.wikipedia.org/wiki/HSL_and_HSV
+-->
<xsl:template name="fill">
<!-- Current wedge number for generating a colour. -->
<xsl:param name="wedge"/>
<!-- Total number of wedges in the pie. -->
<xsl:param name="wedges"/>
<!-- RGB colour in hexadecimal. -->
<xsl:param name="colour"/>
<!-- Derive the colour decimal values from $colour's HEX code. -->
<xsl:variable name="r">
<xsl:call-template name="hex2dec">
<xsl:with-param name="hex"
select="substring($colour, 1, 2)"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="g">
<xsl:call-template name="hex2dec">
<xsl:with-param name="hex"
select="substring($colour, 3, 2)"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="b">
<xsl:call-template name="hex2dec">
<xsl:with-param name="hex"
select="substring($colour, 5, 2)"/>
</xsl:call-template>
</xsl:variable>
<!--
| Convert RGB to XYZ, using nominal range for RGB.
| http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
+-->
<xsl:variable name="r_n" select="$r div 255" />
<xsl:variable name="g_n" select="$g div 255" />
<xsl:variable name="b_n" select="$b div 255" />
<!--
| Assume colours are in sRGB.
| http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
-->
<xsl:variable name="x"
select=".4124564 * $r_n + .3575761 * $g_n + .1804375 * $b_n"/>
<xsl:variable name="y"
select=".2126729 * $r_n + .7151522 * $g_n + .0721750 * $b_n"/>
<xsl:variable name="z"
select=".0193339 * $r_n + .1191920 * $g_n + .9503041 * $b_n"/>
<!--
| Convert XYZ to L*a*b.
| http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
+-->
<xsl:variable name="if_x">
<xsl:call-template name="lab_f">
<xsl:with-param name="xyz_n" select="$x div $X_r"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="if_y">
<xsl:call-template name="lab_f">
<xsl:with-param name="xyz_n" select="$y div $Y_r"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="if_z">
<xsl:call-template name="lab_f">
<xsl:with-param name="xyz_n" select="$z div $Z_r"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="lab_l" select="(116.0 * $if_y) - 16.0"/>
<xsl:variable name="lab_a" select="500.0 * ($if_x - $if_y)"/>
<xsl:variable name="lab_b" select="200.0 * ($if_y - $if_z)"/>
<!--
| Convert L*a*b to LCH.
| http://www.brucelindbloom.com/index.html?Eqn_Lab_to_LCH.html
+-->
<xsl:variable name="lch_l" select="$lab_l"/>
<xsl:variable name="lch_c">
<xsl:call-template name="sqrt">
<xsl:with-param name="n" select="($lab_a * $lab_a) + ($lab_b * $lab_b)"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="lch_h">
<xsl:call-template name="atan2">
<xsl:with-param name="x" select="$lab_b"/>
<xsl:with-param name="y" select="$lab_a"/>
</xsl:call-template>
</xsl:variable>
<!--
| Prevent similar adjacent colours.
| http://math.stackexchange.com/a/936767/7932
+-->
<xsl:variable name="wi" select="$wedge"/>
<xsl:variable name="wt" select="$wedges"/>
<xsl:variable name="w">
<xsl:choose>
<xsl:when test="$wt > 5">
<xsl:variable name="weven" select="(($wi+4) mod ($wt + $wt mod 2))"/>
<xsl:value-of
select="$weven * (1-($wi mod 2)) + ($wi mod 2 * $wi)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$wedge"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- lch_l, lch_c, and lch_h are now set; rotate the hue. -->
<xsl:variable name="lch_wedge_h" select="(360.0 div $wedges) * $wedge"/>
<!--
| Convert wedge's hue-adjusted LCH to L*a*b.
| http://www.brucelindbloom.com/index.html?Eqn_LCH_to_Lab.html
+-->
<xsl:variable name="lab_sin_h">
<xsl:call-template name="sine">
<xsl:with-param name="degrees" select="$lch_wedge_h"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="lab_cos_h">
<xsl:call-template name="cosine">
<xsl:with-param name="degrees" select="$lch_wedge_h"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="final_lab_l" select="$lch_l"/>
<xsl:variable name="final_lab_a" select="$lch_c * $lab_cos_h"/>
<xsl:variable name="final_lab_b" select="$lch_c * $lab_sin_h"/>
<!--
| Convert L*a*b to XYZ.
| http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
+-->
<xsl:variable name="of_y" select="($final_lab_l + 16.0) div 116.0"/>
<xsl:variable name="of_x" select="($final_lab_a div 500.0) + $of_y"/>
<xsl:variable name="of_z" select="$of_y - ($final_lab_b div 200.0)"/>
<xsl:variable name="of_x_pow">
<xsl:call-template name="power">
<xsl:with-param name="base" select="$of_x"/>
<xsl:with-param name="exponent" select="3"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="of_z_pow">
<xsl:call-template name="power">
<xsl:with-param name="base" select="$of_z"/>
<xsl:with-param name="exponent" select="3"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="ox_r">
<xsl:choose>
<xsl:when test="$of_x_pow > $LAB_EPSILON">
<xsl:value-of select="$of_x_pow"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="((116.0 * $of_x) - 16.0) div $LAB_K"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="oy_r">
<xsl:choose>
<xsl:when test="$final_lab_l > ($LAB_K * $LAB_EPSILON)">
<xsl:call-template name="power">
<xsl:with-param name="base"
select="($final_lab_l + 16.0) div 116.0"/>
<xsl:with-param name="exponent"
select="3"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$final_lab_l div $LAB_K"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="oz_r">
<xsl:choose>
<xsl:when test="$of_z_pow > $LAB_EPSILON">
<xsl:value-of select="$of_z_pow"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="((116.0 * $of_z) - 16.0) div $LAB_K"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="X" select="$ox_r * $X_r"/>
<xsl:variable name="Y" select="$oy_r * $Y_r"/>
<xsl:variable name="Z" select="$oz_r * $Z_r"/>
<!--
| Convert XYZ to sRGB.
| http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+-->
<xsl:variable name="R"
select="3.2404542 * $X + -1.5371385 * $Y + -0.4985314 * $Z"/>
<xsl:variable name="G"
select="-0.9692660 * $X + 1.8760108 * $Y + 0.0415560 * $Z"/>
<xsl:variable name="B"
select="0.0556434 * $X + -0.2040259 * $Y + 1.0572252 * $Z"/>
<!-- Round the result. -->
<xsl:variable name="R_r" select="round($R * 255)"/>
<xsl:variable name="G_r" select="round($G * 255)"/>
<xsl:variable name="B_r" select="round($B * 255)"/>
<xsl:text>rgb(</xsl:text>
<xsl:value-of select="concat($R_r, ',', $G_r, ',', $B_r)"/>
<xsl:text>)</xsl:text>
</xsl:template>
<xsl:template name="lab_f">
<xsl:param name="xyz_n"/>
<xsl:choose>
<xsl:when test="$xyz_n > $LAB_EPSILON">
<xsl:call-template name="nthroot">
<xsl:with-param name="index" select="3"/>
<xsl:with-param name="radicand" select="$xyz_n"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="($LAB_K * $xyz_n + 16.0) div 116.0" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Converts a two-digit hexadecimal number to decimal. -->
<xsl:template name="hex2dec">
<xsl:param name="hex"/>
<xsl:variable name="digits" select="'ABCDEF'"/>
<xsl:variable name="X" select="substring($hex, 1, 1)"/>
<xsl:variable name="Y" select="substring($hex, 2, 1)"/>
<xsl:variable name="Xval"
select="string-length(substring-before($digits,$X))"/>
<xsl:variable name="Yval"
select="string-length(substring-before($digits,$Y))"/>
<xsl:value-of select="16 * $Xval + $Yval"/>
</xsl:template>
</xsl:stylesheet>
的Trig,根,和雜項數學函數被留下作爲爲讀者鍛鍊。而且,沒有一個人的頭腦想要在XSLT 1.0中編寫所有這些代碼。另一方面,XSLT 2.0有一個implementation here。
延伸閱讀:
怎麼是藍色的類似綠色的嗎? – peterchen 2008-10-26 01:59:34
@peterchen - 如果你是藍綠色的色盲,則非常相似;) – redcalx 2011-11-05 17:18:27