سؤال

لدي بعض التعليمات البرمجية التي تولد صورة لمخطط دائري.إنها فئة للأغراض العامة، لذا يمكن تقديم أي عدد من الشرائح كمدخل.الآن لدي مشكلة في اختيار الألوان الجيدة للشرائح.هل هناك بعض الخوارزمية الجيدة في ذلك؟

أو ربما ينبغي لي فقط اختيار الألوان الثابتة وإدراجها؟ولكن كم.ربما 10 ألوان ونأمل ألا يكون هناك أكثر من 10 شرائح على الإطلاق؟وأيضًا، أي 10 ألوان تختار؟

يجب أن تتبع الألوان بعض القواعد:

  • إنهم بحاجة إلى أن يبدوا جميلين
  • يجب ألا تكون الألوان المتجاورة متشابهة (يُمنع استخدام اللون الأزرق بجوار اللون الأخضر)
  • لون خلفية الفطيرة هو الأبيض، لذا فإن اللون الأبيض غير متاح

قد تكون بعض الخوارزميات التي تتعامل مع قيم RGB هي الحل المفضل.

هل كانت مفيدة؟

المحلول

سأقوم بتجميع قائمة تضم حوالي 20 لونًا مسبقًا، ثم أبدأ في التكرار باستخدام الثاني لون.بهذه الطريقة لن تكسر قاعدتك الثانية.وأيضًا، إذا قام شخص ما بإنشاء مخطط دائري يحتوي على أكثر من 20 شريحة، فسيواجه مشاكل أكبر.:)

نصائح أخرى

لقد قمت بحلها على النحو التالي:

  1. اختر أ اللون الأساسي.
  2. احسبها مسحة (baseHue).
  3. قم بإنشاء لون بنفس التشبع واللمعان، مع حساب درجة اللون على النحو التالي:
      hue = baseHue + ((240 / pieces) * piece % 240
    

شركة#:

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());

لقد استخدمت فئة HSLColor.

ال مثال على مخططات جوجل يستخدم 12 قطعة ولون أساسي #8A56E2:

Chart Example

نلقي نظرة على لون بروير, ، أداة تساعد على تحديد نظام التلوين لنقل المعلومات النوعية أو الكمية:الخرائط والرسوم البيانية، الخ.من بين "الأنواع" الثلاثة من اللوحات التي يمكن لهذه الأداة إنشاؤها - متسلسلة ونوعية ومتباينة - ربما تحتاج إلى الأخيرة، المتباينة...

يمكنك أيضًا تنزيل ملفات Excel بتعريفات RGB لجميع اللوحات.

بناء على هذا الحل لحل قاعدة السؤال رقم 2، تقوم الخوارزمية التالية بتبديل الألوان حول النقطة الوسطى للفطيرة.المعلمتين:

  1. pNbColors هو عدد الشرائح في الفطيرة
  2. pNonAdjacentSimilarColor قيمة منطقية للإشارة إلى ما إذا كنت تريد الحصول على ألوان مشابهة متجاورة أم لا.

انا استخدم ColorHSL, اللونRGB و 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;
}

وهذا ينتج إخراج الجانب الأيمن:

Comparison Image

فئة اللونHSL:

    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;
        }
    }
}

فئة اللونRGB:

    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 ثم ضبط اللون (مثل أجاب هنا) يخلق سطوعًا ملحوظًا غير متناسق.اللون الأصفر/الأخضر أفتح بشكل ملحوظ من اللون الأزرق/الأرجواني:

Inconsistent

من الممكن الحصول على نتيجة مماثلة دون هذا الاختلاف:

Consistent

خوارزمية

ومع ذلك، فإن الخوارزمية أكثر تعقيدًا بكثير:

  1. تحويل أكواد HTML السداسية العشرية إلى قيم RGB الاسمية (تقسيم المكونات على 255).
  2. تحويل قيم RGB إلى مساحة اللون XYZ;يستخدم مرجع D65 باللون الأبيض إس آر جي بي مساحة العمل.
  3. تحويل من XYZ إلى لأب مساحة اللون.
  4. تحويل من Lأب ل مساحة اللون LCH.
  5. حساب درجة لون إسفين الفطيرة في مساحة الألوان LCH:
    (360.0 div $wedges) * $wedge
  6. أعد حساب اللون الجديد بالراديان.
  7. تحويل مرة أخرى من LCH إلى لأب مساحة اللون باستخدام لون جديد.
  8. تحويل من Lأب ل مساحة اللون XYZ.
  9. تحويل من XYZ إلى مساحة اللون إس آر جي بي.
  10. اضرب قيم RGB في 255.

تطبيق

فيما يلي مثال للتنفيذ في 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 &gt; 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 &gt; $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 &gt; ($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 &gt; $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 &gt; $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="'0123456789ABCDEF'"/>
  <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>

تُترك وظائف الرياضيات المثلثة والجذرية والمتنوعة كتمرين للقارئ.وأيضًا، لن يرغب أي شخص بكامل قواه العقلية في ترميز كل هذا في XSLT 1.0.من ناحية أخرى، يحتوي XSLT 2.0 على التنفيذ هنا.

موارد

قراءة متعمقة:

هذه الورقة البحثية لعام 1985 التي كتبها "ROSS E.ROLEY, CAPT" يعطي خوارزمية لتعظيم فصل الألوان لمجموعة عشوائية من الألوان (كاملة مع التعليمات البرمجية في FORTRAN).

(يبدو أن فصل الألوان يمثل مشكلة تصورية مهمة للقوات العسكرية لمنع حوادث اللون الأزرق على الأزرق.)

ومع ذلك، إذا كنت تريد الالتزام بمجموعة مكونة من 20 لونًا، فسيكون الحل السريع والبسيط هو اختيار رؤوس الاثني عشر وجهًا وتحويل إحداثيات (x,y,z) (بمقياس مناسب) إلى (r,g, ب).

يوجد مولد هنا.إنه مخصص لتصميم الويب، لكن الألوان ستبدو رائعة على المخطط الدائري أيضًا.

يمكنك إما تجميع قائمة من الألوان الجميلة مسبقًا، أو فحص المنطق الكامن وراء المولد والقيام بشيء مماثل بنفسك.

لقد وجدت صيغة الكود الزائف هذه التي قد تساعد.يمكنك البدء بمجموعة لزراعتها.

صيغة اختلاف اللون

فيما يلي الصيغة التي اقترحتها W3C لتحديد الفرق بين لونين.

(الحد الأقصى (القيمة الحمراء 1، القيمة الحمراء 2) - الحد الأدنى (القيمة الحمراء 1، القيمة الحمراء 2)) + (الحد الأقصى (القيمة الخضراء 1، القيمة الخضراء 2) - الحد الأدنى (القيمة الخضراء 1، القيمة الخضراء 2)) + (الحد الأقصى (القيمة الزرقاء 1، القيمة الزرقاء 2) - الحد الأدنى (القيمة الزرقاء 1، القيمة الزرقاء 2))

يجب أن يكون الفرق بين لون الخلفية ولون المقدمة أكبر من 500.

هنا هو المصدر

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top