2014-02-23 71 views
0

當前正在應用程序中,並試圖從提供的顏色中找到顏色(互補,分割 - 補充,類似,三元組,四方形等)基本顏色。顏色和諧理論和算法,計算互補,三元組,四元等

什麼,我現在在做什麼:

  1. 轉換RGB顏色到HSV
  2. 調整水平值,以繞過360度滾輪顏色(S和V值不變)
  3. 轉換HSV回RGB

下面是三元組的示例(HSV對象表示基色):

colors.Add(new HSVData() { h = hsv.h + 120, s = hsv.s, v = hsv.v }); 
colors.Add(new HSVData() { h = hsv.h - 120, s = hsv.s, v = hsv.v }); 

而對於廣場:

colors.Add(new HSVData() { h = hsv.h + 90, s = hsv.s, v = hsv.v }); 
colors.Add(new HSVData() { h = hsv.h + 180, s = hsv.s, v = hsv.v }); 
colors.Add(new HSVData() { h = hsv.h + 270, s = hsv.s, v = hsv.v }); 

RGB到HSV:

public static HSVData RGBtoHSV(RGBResult RGB) 
{ 
    double min; 
    double max; 
    double delta; 

    double r = (double)RGB.r/255; 
    double g = (double)RGB.g/255; 
    double b = (double)RGB.b/255; 

    double h; 
    double s; 
    double v; 

    min = Math.Min(Math.Min(r, g), b); 
    max = Math.Max(Math.Max(r, g), b); 
    v = max; 
    delta = max - min; 
    if (max == 0 || delta == 0) 
    { 
     s = 0; 
     h = 0; 
    } 
    else 
    { 
     s = delta/max; 
     if (r == max) 
     { 
      // Between Yellow and Magenta 
      h = (g - b)/delta; 
     } 
     else if (g == max) 
     { 
      // Between Cyan and Yellow 
      h = 2 + (b - r)/delta; 
     } 
     else 
     { 
      // Between Magenta and Cyan 
      h = 4 + (r - g)/delta; 
     } 
    } 

    h *= 60; 
    if (h < 0) 
    { 
     h += 360; 
    } 

    return new HSVData() 
    { 
     h = (int)(h/360 * 255), 
     s = (int)(s * 255), 
     v = (int)(v * 255) 
    }; 
} 

HSV到RGB:

public static Color ConvertHsvToRgb(float h, float s, float v) 
{ 
    byte MAX = 255; 

    h = h/360; 
    if (s > 0) 
    { 
     if (h >= 1) 
      h = 0; 
     h = 6 * h; 
     int hueFloor = (int)Math.Floor(h); 
     byte a = (byte)Math.Round(MAX * v * (1.0 - s)); 
     byte b = (byte)Math.Round(MAX * v * (1.0 - (s * (h - hueFloor)))); 
     byte c = (byte)Math.Round(MAX * v * (1.0 - (s * (1.0 - (h - hueFloor))))); 
     byte d = (byte)Math.Round(MAX * v); 

     switch (hueFloor) 
     { 
      case 0: return Color.FromArgb(MAX, d, c, a); 
      case 1: return Color.FromArgb(MAX, b, d, a); 
      case 2: return Color.FromArgb(MAX, a, d, c); 
      case 3: return Color.FromArgb(MAX, a, b, d); 
      case 4: return Color.FromArgb(MAX, c, a, d); 
      case 5: return Color.FromArgb(MAX, d, a, b); 
      default: return Color.FromArgb(0, 0, 0, 0); 
     } 
    } 
    else 
    { 
     byte d = (byte)(v * MAX); 
     return Color.FromArgb(255, d, d, d); 
    } 
} 

我得到的顏色根據許多在線顏色工具是錯誤的!我應該使用HSV的HSL?我究竟做錯了什麼?

在線工具相比:提前

http://colorschemedesigner.com/

http://www.colorsontheweb.com/colorwizard.asp

謝謝!

+0

向我們展示你的轉換例程,從RGB到HSV和HSV到RGB。並告訴我們*他們怎麼錯了。顯示示例輸入和實際輸出,以及預期輸出。 –

+0

感謝您的回覆,我編輯了我原來的帖子。 – JPSavard

回答

2

您期望在ConvertHsvToRgb方法中獲得什麼值範圍?它看起來對我來說,那就是:

0 <= h <= 360 
0 <= s <= 1.0 
0 <= v <= 1.0 

你不告訴你是如何調用此方法,但如果你不及格值在這些範圍內,就不會得到正確的轉換。如果你打算減去色調,你可能想要包括一種將色調歸一化爲0-360的方法,就像你在黑社會中做的那樣。

我認爲你的轉換是正確的,除非你不應該將你的h,s,v值轉換爲整數;在上面所示的範圍內將它們保持爲雙打。

public static HSVData RGBtoHSV(Color RGB) 
{ 
    double r = (double)RGB.R/255; 
    double g = (double)RGB.G/255; 
    double b = (double)RGB.B/255; 

    double h; 
    double s; 
    double v; 

    double min = Math.Min(Math.Min(r, g), b); 
    double max = Math.Max(Math.Max(r, g), b); 
    v = max; 
    double delta = max - min; 
    if (max == 0 || delta == 0) 
    { 
     s = 0; 
     h = 0; 
    } 
    else 
    { 
     s = delta/max; 
     if (r == max) 
     { 
      // Between Yellow and Magenta 
      h = (g - b)/delta; 
     } 
     else if (g == max) 
     { 
      // Between Cyan and Yellow 
      h = 2 + (b - r)/delta; 
     } 
     else 
     { 
      // Between Magenta and Cyan 
      h = 4 + (r - g)/delta; 
     } 

    } 

    h *= 60; 
    if (h < 0) 
    { 
     h += 360; 
    } 

    return new HSVData() 
    { 
     h = h, 
     s = s, 
     v = v 
    }; 
} 

現在您可以直接將這些h,s,v valuew傳遞給ConvertHsvToRgb方法。我已經將參數改爲加倍,驗證飽和度和值輸入,並對色調進行歸一化。

public static Color ConvertHsvToRgb(double h, double s, double v) 
{ 
    Debug.Assert(0.0 <= s && s <= 1.0); 
    Debug.Assert(0.0 <= v && v <= 1.0); 

    // normalize the hue: 
    while (h < 0) 
     h += 360; 
    while (h > 360) 
     h -= 360; 

    h = h/360; 

    byte MAX = 255; 

    if (s > 0) 
    { 
     if (h >= 1) 
      h = 0; 
     h = 6 * h; 
     int hueFloor = (int)Math.Floor(h); 
     byte a = (byte)Math.Round(MAX * v * (1.0 - s)); 
     byte b = (byte)Math.Round(MAX * v * (1.0 - (s * (h - hueFloor)))); 
     byte c = (byte)Math.Round(MAX * v * (1.0 - (s * (1.0 - (h - hueFloor))))); 
     byte d = (byte)Math.Round(MAX * v); 

     switch (hueFloor) 
     { 
      case 0: return Color.FromArgb(MAX, d, c, a); 
      case 1: return Color.FromArgb(MAX, b, d, a); 
      case 2: return Color.FromArgb(MAX, a, d, c); 
      case 3: return Color.FromArgb(MAX, a, b, d); 
      case 4: return Color.FromArgb(MAX, c, a, d); 
      case 5: return Color.FromArgb(MAX, d, a, b); 
      default: return Color.FromArgb(0, 0, 0, 0); 
     } 
    } 
    else 
    { 
     byte d = (byte)(v * MAX); 
     return Color.FromArgb(255, d, d, d); 
    } 
} 

根據我的測試中,這兩種方法現在給出了從RGB到HSV和背部的任何顏色「往返」轉換。

對於「黑社會」,你正在調整從原來的顏色+/- 120度。因此,例如,如果您以紅色作爲基本顏色,則+/- 120度顏色爲綠色和藍色。這些轉換似乎正常工作:

HSVData hsv = HSVData.RGBtoHSV(Color.FromArgb(255, 0, 0)); 
HSVData hsv2 = new HSVData() { h = hsv.h + 120, s = hsv.s, v = hsv.v }; 
HSVData hsv3 = new HSVData() { h = hsv.h - 120 , s = hsv.s, v = hsv.v }; 

Color red = HSVData.ConvertHsvToRgb(hsv.h, hsv.s, hsv.v); 
Color green = HSVData.ConvertHsvToRgb(hsv2.h, hsv2.s, hsv2.v); 
Color blue = HSVData.ConvertHsvToRgb(hsv3.h, hsv3.s, hsv3.v); 

HSVData hsv4 = HSVData.RGBtoHSV(Color.YellowGreen); 
Color yellowGreen = HSVData.ConvertHsvToRgb(hsv4.h, hsv4.s, hsv4.v); 
+0

謝謝,我終於發現我在hsv => rgb轉換中遇到了問題。但現在看來,無論我選擇哪種顏色,它總是隻會在我的三聯體,四聯體,補體中給予紅色,綠色,藍色或黃色。 – JPSavard

+0

查看我上面的編輯到您的轉換方法 - 我相信他們會給您正確的轉換 – Doug

+0

第一個(紅色)顯示您可以從RGB轉換爲HSV並返回RGB,並再次以紅色結束(與YellowGreen相同)。對於綠色和藍色,我發現,當您將紅色偏移+/- 120度並轉換回RGB時,您會如預期的那樣變成綠色和藍色。我將轉換回到RGB,因爲它更容易看到它是什麼顏色。但是,HSV(120,1,1)是綠色的RGB(0,255,0)。 – Doug