2011-12-12 56 views
4

我通常使用下面的代碼來生成隨機顏色:如何隨機生成完全飽和的顏色?

Random rand = new Random(); 

Color random = Color.FromArgb((int)(rand.NextDouble() * 255), 
           (int)(rand.NextDouble() * 255), 
           (int)(rand.NextDouble() * 255)); 

但大多看起來像一個灰色的變化。我怎樣才能限制輸出只有完全飽和的顏色?

謝謝。

+2

表達式'(int)(rand.NextDouble()* 255)'永遠不會生成值「255」。 'NextDouble'生成一個數字,使得0 <= x <1.0。如果你想產生從0到255的數值,你需要把你的數字改成256.但是,爲什麼不使用'rand.Next(256)'來完成它呢? –

+0

很高興知道,吉姆 – abenci

回答

4

理論

完全飽和(13759 HSL和類似的配色方案),實際上意味着,你必須在一個完整的RGB值,一個0,一個在任何其他值。

其原因是飽和度是基於最高和最低顏色成分之間的差異,並且當它們處於極端時是最高的。實際的定義更加複雜(並涉及亮度),但足夠說一個0和另一個1的分量將給出最大飽和度。

算法1

這導致這樣做的一個比較簡單的方法。

  1. 生成隨機數0和1之間
  2. 隨機
  3. 分配這個號碼到一個FO的R,G和B的元素。
  4. 將零隨機分配給其餘元素之一。
  5. 設定的最後一個元素爲1

這會給你一個最大飽和度的顏色相對簡單。

對於實現它可能是最容易產生一個隨機數1到6爲6可能的選擇你分配0,1和隨機元素,然後使用某種類型的開關。

這是最簡單的算法,但由於選擇/分支不一定是最簡單的實現。

算法2

的建議由吉姆·米契爾基於類似的理論,但只是實現了一個稍微不同的第二種方法。

  1. 產生用於每個R,G和B分量
  2. 的隨機值查找最大分量。
  3. 找到最小組件。
  4. 將最大分量設置爲1.
  5. 將最小分量設置爲0。

這與將一個值設置爲1,一個設置爲0和一個設置爲隨機值的效果相同。它的優點是它不需要你使用凌亂的switch語句,但是你最終可能會產生一些混亂的循環。同樣取決於你的組件的精度(例如,如果你直接用字節),那麼如果你的中間值實際上等於你的頂部或底部(或所有三個都是相同的),那麼這可能也會被重置,這取決於你如何編碼你的算法。這將主要影響隨機性的傾斜,但這不太可能引人注意。吉姆

int[] rgb = new int[3]; 
    rgb[0] = rnd.Next(256); // red 
    rgb[1] = rnd.Next(256); // green 
    rgb[2] = rnd.Next(256); // blue 

    // Console.WriteLine("{0},{1},{2}", rgb[0], rgb[1], rgb[2]); 

    // find max and min indexes. 
    int max, min; 

    if (rgb[0] > rgb[1]) 
    { 
     max = (rgb[0] > rgb[2]) ? 0 : 2 
     min = (rgb[1] < rgb[2]) ? 1 : 2; 
    } 
    else 
    { 
     max = (rgb[1] > rgb[2]) ? 1 : 2; 
     int notmax = 1 + max % 2; 
     min = (rgb[0] < rgb[notmax]) ? 0 : notmax; 
    } 
    rgb[max] = 255; 
    rgb[min] = 0; 

    // Console.WriteLine("{0},{1},{2}", rgb[0], rgb[1], rgb[2]); 
+0

有趣的另一種方法是產生三個隨機數(對於R,G和B)。然後,推動最高到1和最低到0 –

+0

是的,這也可以工作,幾乎肯定會是整潔的代碼,沒有雜亂的開關 – Chris

+0

@JimMischel:我已經在你的建議中加入了我的答案。假設你不介意... – Chris

2

我想你想在HSL值中產生你的顏色,設置飽和度固定在它的最大值,只有隨機化色調和亮度。你可以找到HSL顏色here的課程。

+0

它可能是你想要固定在0.5(即中點)亮度,因爲它往往是白色,並低於黑色,所以你可能會結束與以前相同的顏色聚束問題即越接近0和1,亮度越小,即使在最大飽和度下,你也會看到不同的H差異。 – Chris

0

的方法,兩人還禮貌爲了記錄

代碼實現,這裏是一個小的適應吉姆·米契爾建議(下面是Java代碼,適應.NET是微不足道的):

private static Random r = new Random(); 

public static final String randomColor() { 
    int[] arr = new int[3]; 
    arr[0] = 0x80; 
    arr[1] = 0xFF; 
    arr[2] = r.nextInt(0x10) * 8 + 0x80; 
    // Fisher–Yates shuffle 
    for (int i1 = arr.length - 1; i1 >= 0; i1--) { 
     int i2 = r.nextInt(i1 + 1); 
     int tmp = arr[i2]; 
     arr[i2] = arr[i1]; 
     arr[i1] = tmp; 
    } 
    return String.format("%02x%02x%02x", arr[0], arr[1], arr[2]); 
} 

我們集3個值中隨機:

  • ö ne到0x80
  • 另一個0xFF
  • 剩餘的一個到0X80到0xFF之間的一個隨機值。

隨機值與的0x10的步驟產生得到一組不同顏色的減少(即6×8 = 48),則可以寫爲arr[2] = r.nextInt(0x80) + 0x80;更多的選擇。

我也將最小值設置爲0x80以獲得飽和度較低的顏色,這在我看來更好看一些(這是一個不好的味道......)。你可以減少這個最小值來增加飽和度。