对角非线性梯度的算法

Algorithm for a diagonal non-linear gradient

我正在寻找生成以下图像的算法:

我只对正方形左上半部分(对角线)显示的数据感兴趣。


我目前处于一个起点,我有以下简单的线性函数:

double GetColorAt(double x, double y)
{
   return 1 - (x + y);
}

其中 x 从左到右,y 从上到下在 [0...1] 的范围内。 return 值是 [0...1] 范围内 RGB 通道的颜色分量。它为我生成了这个:

如果有人喜欢通过查看十六进制而不是图像来测试他们关于如何生成渐变的理论,以下内容可能会有所帮助。它被缩小了 10 倍到 25 像素 25 像素。

0000000: ff fe fd fa f7 f3 ed e8 e1 d9 d1 c8 be b2 a7 9a 8c 7e 6e 5e 4d 3c 2a 12 18  .................~n^M<*..
0000019: ff fe fc fa f6 f1 ec e6 de d6 cd c3 b8 ac 9f 91 83 73 62 51 3e 2c 15 08 1e  .................sbQ>,...
0000032: ff fe fc f9 f5 f0 ea e3 db d2 c8 bd b1 a4 96 87 77 66 54 41 2d 17 02 06 20  ................wfTA-... 
000004b: ff fe fc f9 f4 ef e8 e1 d8 ce c3 b7 aa 9c 8c 7c 6a 58 44 2f 18 04 00 06 20  ...............|jXD/.... 
0000064: ff fe fb f8 f3 ed e6 de d4 c9 bd b0 a1 92 81 6f 5b 47 31 1a 04 00 00 06 20  ...............o[G1..... 
000007d: ff fe fb f7 f2 eb e3 da cf c4 b6 a8 98 86 74 60 4a 34 1b 04 00 01 00 06 20  ..............t`J4...... 
0000096: ff fe fb f6 f0 e9 e0 d6 ca bd ae 9e 8c 79 64 4e 37 1c 05 00 00 00 00 06 20  .............ydN7....... 
00000af: ff fd fa f5 ef e7 dd d1 c4 b5 a5 93 7f 69 52 3a 1d 03 00 00 00 00 00 06 20  .............iR:........ 
00000c8: ff fd f9 f4 ed e4 d9 cc bd ac 9a 85 6f 57 3d 20 05 00 00 00 00 00 00 06 20  ............oW= ........ 
00000e1: ff fd f9 f3 ea e0 d3 c5 b4 a1 8c 75 5c 41 22 05 00 00 00 00 00 00 00 06 20  ...........u\A"......... 
00000fa: ff fd f8 f1 e7 dc cd bd a9 94 7c 61 45 25 06 00 00 00 00 00 00 00 00 06 20  ..........|aE%.......... 
0000113: ff fc f7 ef e4 d6 c6 b2 9c 84 68 4a 28 07 00 00 00 00 00 00 00 00 00 06 20  ..........hJ(........... 
000012c: ff fc f5 ec df cf bc a6 8c 6f 4f 2b 08 00 00 00 00 00 00 00 00 00 00 06 20  .........oO+............ 
0000145: ff fb f4 e9 da c7 b0 96 77 56 2e 08 00 00 00 00 00 00 00 00 00 00 00 06 20  ........wV.............. 
000015e: ff fa f1 e4 d2 bc a1 81 5d 33 09 00 01 00 00 00 00 00 00 00 00 00 00 06 20  ........]3.............. 
0000177: fe f9 ee de c8 ad 8c 66 38 0a 00 01 00 00 00 00 00 00 00 00 00 00 00 06 20  .......f8............... 
0000190: fe f8 ea d6 bb 99 70 3f 0c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 06 20  ......p?................ 
00001a9: fe f6 e5 cb a8 7d 47 0d 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 06 1f  .....}G..................
00001c2: fe f3 dc ba 8d 51 0f 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 20  .....Q.................. 
00001db: fd ee ce a0 5e 12 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 20  ....^................... 
00001f4: fc e6 b9 70 16 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 1f  ...p.....................
000020d: fa d9 89 1d 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 20  ........................ 
0000226: f9 b4 26 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 20  ..&..................... 
000023f: e6 40 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 20  .@...................... 
0000258: 74 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 20  t....................... 

你走运了,这是我无法抗拒的谜题。

分析图像,有两件事跳出来了。

  • r = g = b,即这是一张纯灰度图。
  • r + a = 255.

这大大简化了事情,这意味着您只需分析一个通道即可获得梯度的完整表征。

这是图像第 0 行和第 128 行的 R 值图:

这个情节非常类似于子弹被重力拉下时的弧线。因此,我将基本方程代入 Excel 并要求它针对 ab 的不同值求解与第 0 行最接近的匹配项 255 - (a*(b*x)^2)。它得出了 a=6.998191873b=0.023556823 的值。当我替换 x/2 时,这些值也与第 128 行中的值密切相关,所以我知道我在正确的轨道上。

这是Python中的算法:

for y in range(height):
    scale = (256 - y) / 256.0
    for x in range(width):
        r = int(round(255 - (6.998191873 * (0.023556823 * x/scale) ** 2)))
        r = max(r, 0)
        ld2[x, y] = (r, r, r, 255-r)

不太准确,这在图像底部最明显,似乎有一个像素偏移。但它在视觉上完全相同。