2009-02-06 60 views
5

我有一個2D位圖數組,比如500 * 500的值。我試圖在數組上創建一個線性漸變,所以得到的位圖看起來像這樣(灰度): Example gradient http://showandtell-graphics.com/images/gradient/gradient_12.jpg在二維數組中創建一個線性漸變

輸入將是要填充的數組,兩個點(如開始和結束指向Photoshop/GIMP中的漸變工具)以及將使用的值範圍。

我目前最好的結果是這樣的:

alt text http://img222.imageshack.us/img222/1733/gradientfe3.png

...這是隔靴搔癢,我想達到的目標。它看起來更像是一個徑向漸變。

創建這樣的漸變最簡單的方法是什麼?我將用C++實現它,但我想要一些通用算法。

回答

3

在您的示例圖像中,它看起來像有一個徑向漸變。這是我需要的步驟的impromtu數學解釋。對數學抱歉,其他答案在實施方面更好。

  1. 定義一個線性函數(如y = x + 1),該域(即x)是從您想要開始的顏色到您想要結束的顏色。您可以根據Ox0到0xFFFFFF範圍(24位顏色)來考慮這一點。如果你想處理亮度等事情,你必須對範圍做一些技巧(即y值)。
  2. 接下來,您需要在您有的矩陣上映射矢量,因爲它定義了顏色將改變的方向。此外,由線性函數定義的顏色值將在矢量的每個點處指定。矢量的開始點和結束點也定義了域中的最小值和最大值。您可以將矢量看作您漸變的一條線。
  3. 對於矩陣中的每個單元格,可以從單元格的垂直線與矢量相交的矢量爲顏色指定一個值。請參閱下圖,其中c是單元格的位置。是交點。如果你假裝的顏色在。是紅色的,那麼這就是你要分配給單元格的東西。
 
      | 
      c 
      | 
      | 
    Vect:____.______________ 
      | 
      | 

14

這實際上是一個數學問題,所以它是否真的屬於堆棧溢出可能是有爭議的,但無論如何:您需要將圖像中每個點的座標投影到漸變的軸上,並使用該座標協調確定顏色。

數學,我的意思是:

  1. 說你的出發點是(X1,Y1)和你的結束點是(X2,Y2)
  2. 計算A = (x2 - x1)B = (y2 - y1)
  3. 計算C1 = A * x1 + B * y1爲起點和終點的C2 = A * x2 + B * y2C2應該大於C1
  4. 對於圖像中的每個點,計算C = A * x + B * y
  5. 如果C <= C1,使用起始顏色;如果C >= C2,使用結束顏色;否則,使用加權平均值:

    (start_color * (C2 - C) + end_color * (C - C1))/(C2 - C1)

我做了一些快速測試,以檢查該基本工作。

+3

+1,如果沒有應用數學,什麼是編程? =) – Crashworks 2009-02-06 19:31:07

+0

也許我很愚蠢,但我無法讓它工作。它適用於水平和垂直漸變,但沒有角度的運氣。反正+1。 – 2009-02-06 20:43:23

+0

只需再次檢查,在Mathematica中,它可以完美適用於我測試的所有角度,所以我相當肯定公式本身是有效的。你有什麼麻煩? – 2009-02-06 23:00:24

1

我只是張貼我的解決方案。

int ColourAt(int x, int y) 
{ 
    float imageX = (float)x/(float)BUFFER_WIDTH; 
    float imageY = (float)y/(float)BUFFER_WIDTH; 

    float xS = xStart/(float)BUFFER_WIDTH; 
    float yS = yStart/(float)BUFFER_WIDTH; 
    float xE = xEnd/(float)BUFFER_WIDTH; 
    float yE = yEnd/(float)BUFFER_WIDTH; 
    float xD = xE - xS; 
    float yD = yE - yS; 

    float mod = 1.0f/(xD * xD + yD * yD); 

    float gradPos = ((imageX - xS) * xD + (imageY - yS) * yD) * mod; 

    float mag = gradPos > 0 ? gradPos < 1.0f ? gradPos : 1.0f : 0.0f; 

    int colour = (int)(255 * mag); 
    colour |= (colour << 16) + (colour << 8); 
    return colour; 
} 

對於加速ups,緩存導出的「方向」值(提示:預乘magn)。

0

這個問題有兩個部分。

  1. 鑑於兩種顏色A和B一定比例P,確定什麼顏色就在於從P「的方式百分比」到B

  2. 鑑於在一個平面上的一個點,找到正交投影那點到一個給定的線上。

第2部分給定的行是您的漸變線。給定任意點P,將其投影到漸變線上。假設它的投影是R.然後確定R距梯度線段起點有多遠,以梯度線段長度的百分比表示。在上面第1部分的函數中使用這個百分比。這就是P應該是的顏色。

請注意,與其他人所說的相反,您不能在第1部分的函數中將您的顏色視爲常規數字。這幾乎肯定不會達到您想要的效果。你所做的取決於你使用的色彩空間。如果您想要RGB漸變,那麼您必須分別查看紅色,綠色和藍色的顏色成分。

例如,如果你想 「半路之間的」 純紅色和藍色的顏色,然後在16進制你正在處理

FF 00 00

00 00 FF

也許你想要的顏色是一樣的東西

這是一個很好的紫色。您必須分別平均每個顏色分量。如果您嘗試直接對十六進制數0xff0000和0x0000ff求平均值,則會得到0x7F807F,這是一種中等灰度。我猜這至少解釋了上面圖片的部分問題。

或者,如果您處於HSV色彩空間中,您可能只想調整色相分量,並保持原樣。