سؤال

كيف يمكنك أن تذهب نحو اتخاذ مجموعة من الألوان RGB متباعدة بشكل متساو فوق الطيفية اللون ؟ بحيث تبدو وكأنها حقيقية قوس قزح.

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

المحلول

استخدم HSL بدلا من ذلك: إصلاح السطوع والتشبع وتختلف هوى 0-360، ثم تحويلها إلى RGB.

وHSL يصف الألوان كما ينظر إليها من قبل الناس. يصف RGB منهم أنها تستخدم من قبل الأجهزة. لذلك لا يمكنك حقا أن تفعل أي شيء ارضاء بصريا مباشرة باستخدام RGB.

نصائح أخرى

ويمكنك استخدام HSV لون الفضاء و السير عبر البعد هوى.

أبسط النهج هو أن تفعل الخطية (RGB) بين كل متتالية الزوج في هذا التسلسل:

  • #ff0000 الأحمر
  • #ffff00 الأصفر
  • #00ff00 الأخضر
  • #00ffff سماوي
  • #0000ff الأزرق
  • #ff00ff أرجواني
  • #ff0000 العودة إلى الأحمر

هذا ينبغي أن تحصل على تقريبا نفس النتيجة التي تجتاح هوى القيم في هامبورغ أو الأعرج ، ولكن يتيح لك العمل مباشرة في RGB.لاحظ أن عنصر واحد فقط التغييرات لكل الاستيفاء ، الذي يبسط الأمور.وهنا الثعبان التنفيذ:

def rainbow():
  r, g, b = 255, 0, 0
  for g in range(256):
    yield r, g, b
  for r in range(255, -1, -1):
    yield r, g, b
  for b in range(256):
    yield r, g, b
  for g in range(255, -1, -1):
    yield r, g, b
  for r in range(256):
    yield r, g, b
  for b in range(255, -1, -1):
    yield r, g, b
  • الأحمر (ويب اللون) (Hex:#FF0000) (RGB:255, 0, 0)
  • البرتقال (عجلة اللون البرتقالي) (Hex:#FF7F00) (RGB:255, 127, 0)
  • الأصفر (ويب اللون) (Hex:#FFFF00) (RGB:255, 255, 0)
  • الأخضر (X11) (الكهربائية الخضراء) (HTML/CSS "الجير") (عجلة اللون الأخضر) (Hex:#00FF00) (RGB:0, 255, 0)
  • الأزرق (ويب اللون) (Hex:#0000FF) (RGB:0, 0, 255)
  • النيلي (الكهربائية النيلي) (Hex:#6600FF) (RGB:102, 0, 255)
  • البنفسجي (الكهربائية البنفسجي) (Hex:#8B00FF) (RGB:139, 0, 255)

بين كل لون جعل الخطية.

وهذه الفئة سوف نفعل ذلك مع PHP، تمرير المنشئ عدد الألوان التي تريدها في قوس قزح والممتلكات $ تسلسل سيتضمن مجموعة من رموز عرافة rrggbb.

class color
{
    public $sequence = array();

    /**
     * constructor fills $sequence with a list of colours as long as the $count param
     */
    public function __construct($count, $s = .5, $l = .5)
    {
        for($h = 0; $h <= .85; $h += .85/$count)    //.85 is pretty much in the middle of the violet spectrum
        {
            $this->sequence[] = color::hexHSLtoRGB($h, $s, $l);
        }
    }

    /**
     * from https://stackoverflow.com/questions/3597417/php-hsv-to-rgb-formula-comprehension#3642787
     */
    public static function HSLtoRGB($h, $s, $l)
    {

        $r = $l;
        $g = $l;
        $b = $l;
        $v = ($l <= 0.5) ? ($l * (1.0 + $s)) : (l + $s - l * $s);
        if ($v > 0){
              $m;
              $sv;
              $sextant;
              $fract;
              $vsf;
              $mid1;
              $mid2;

              $m = $l + $l - $v;
              $sv = ($v - $m ) / $v;
              $h *= 6.0;
              $sextant = floor($h);
              $fract = $h - $sextant;
              $vsf = $v * $sv * $fract;
              $mid1 = $m + $vsf;
              $mid2 = $v - $vsf;

              switch ($sextant)
              {
                    case 0:
                          $r = $v;
                          $g = $mid1;
                          $b = $m;
                          break;
                    case 1:
                          $r = $mid2;
                          $g = $v;
                          $b = $m;
                          break;
                    case 2:
                          $r = $m;
                          $g = $v;
                          $b = $mid1;
                          break;
                    case 3:
                          $r = $m;
                          $g = $mid2;
                          $b = $v;
                          break;
                    case 4:
                          $r = $mid1;
                          $g = $m;
                          $b = $v;
                          break;
                    case 5:
                          $r = $v;
                          $g = $m;
                          $b = $mid2;
                          break;
              }
        }
        return array('r' => floor($r * 255.0),
                    'g' => floor($g * 255.0), 
                    'b' => floor($b * 255.0)
                    );
    }

    //return a hex code from hsv values
    public static function hexHSLtoRGB($h, $s, $l)
    {
        $rgb = self::HSLtoRGB($h, $s, $l);
        $hex = base_convert($rgb['r'], 10, 16) . base_convert($rgb['g'], 10, 16) . base_convert($rgb['b'], 10, 16);
        return $hex;
    }
}

لاختبار منها مثلا:

$c = new color(100);
foreach($c->sequence as $col)
  print "<div style='background-color:#$col'>$col</div>\n";

وأنا فقط ينسب الفضل للتغليف هذا الأمر في طبقة، تم العثور على وظيفة الأصلي في هذا المنصب: HSV إلى RGB صيغة الفهم

وحلول أخرى تتطلب كميات كبيرة بدلا من رمز والمتفرعة المشروط، مما يجعلها غير صالحة للوحدات معالجة الرسومات. وصلت مؤخرا إلى ما يلي صيغة بسيطة سحرية في GLSL. انها في الأساس نفسه في OpenCL:

vec3 HueToRGB(float hue) {
  vec3 h = vec3(hue, hue + 1.0/3.0, hue + 2.0/3.0);
  return clamp(6.0 * abs(h - floor(h) - 0.5) - 1.0, 0.0, 1.0);
}

وهذا سوف يعطيك لون قوس قزح الذي يتوافق مع قيمة هوى الواردة في RGB الخطي. لاستخدامها في صورة، تحويل إلى sRGB ثم ضرب من قبل 255.

وهنا هو نسخة C ++:

float clamp(float value, float low, float high) {
  return value < low ? low : (value > high ? high : value);
}
void HueToRGB(float hue, float *rgb) {
  rgb[0] = hue;
  rgb[1] = hue + 1.f/3.f;
  rgb[2] = hue + 2.f/3.f;
  for (unsigned i = 0; i < 3; ++i) {
    rgb[i] = clamp(6.0f * fabsf(rgb[i] - floorf(rgb[i]) - 0.5f) - 1.f, 0.f, 1.f);
  }
}

والمفتاح هنا هو أن ندرك أن الرسم البياني لكل من R، G، وينسق B في وظيفة من قيمة هوى هي قيمة فرضت وظيفة مثلث الدورية، والتي يمكن الحصول عليها كقيمة مطلقة من سن منشار وظيفة، x - floor(x).

وأنا أعلم أنه هو بالأحرى السؤال القديم، ولكن هنا هي لغتي بسيطة وسهلة الفهم الحل، الذي يجب أن يكون سهل الاستخدام في معظم لغات البرمجة. استبدال الخطوات وwhichStep مع القيم الخاصة بك.

int steps = 1280;
int stepChange = 1280 / steps;
int change = stepChange * whichStep;
int r=0, g=0, b=0;

if (change < 256)
{
    r = 255;
    g += change;
}
else if (change < 512)
{
    r = 511 - change;
    g = 255;
}
else if (change < 768)
{
    g = 255;
    b = change-512;
}
else if (change < 1024)
{
    g = 1023 - change;
    b = 255;
}
else
{
    r = change - 1024;
    b = 255;
}

وأنا يمكن رسم قوس قزح برمجيا مع جافا سكريبت وHTML5.

وأنا جعل التدرج من RGB (255،0،0) -> RGB (255،255،0) -> RGB (0،255،0) -> RGB (0255255) -> RGB (0،0،255) -> RGB ( 255،0،255).

وI حساب القيم لون عرافة على طول التدرج باستخدام بلدي RainbowVis-JS مكتبة (التي مجرد سلاسل التدرجات معا). أود أن ألفت قوس <م> شكل مع HTML5 قماش، حلقات من خلال الألوان.

<!DOCTYPE html>
<html>
  <head>
    <script src="rainbowvis.js"></script>
  </head>
  <body>
    <script type="text/javascript">
      window.onload = function(){

        var RAINBOW_WIDTH = 60;
        var RAINBOW_RADIUS = 130;

        // Library class
        var rainbow = new Rainbow();
        rainbow.setNumberRange(1, RAINBOW_WIDTH);
        rainbow.setSpectrum(
          'FF0000', 'FFFF00', '00FF00',
          '00FFFF', '0000FF', 'FF00FF'
        );

        // Canvas
        var canvas = document.getElementById('MyCanvas');
        var context = canvas.getContext('2d');

        context.lineWidth = 1;
        for (var i = 1; i <= RAINBOW_WIDTH; i++) {
          context.beginPath();
          context.arc(canvas.width/2, canvas.width/2, RAINBOW_RADIUS - i+1, 
            Math.PI, 0, false);
          context.strokeStyle = '#' + rainbow.colourAt(i); // Library function
          context.stroke();
        }
      };
    </script>
    <canvas id="MyCanvas" width="300" height="300">
      <p>Rainbow arc example. Your browser doesn't support canvas.</p>
    </canvas>
  </body>
</html>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top