如何插入一个颜色序列
How to interpolate a color sequence?
我需要插入或逐渐改变颜色序列,所以它从colorA到colorB到colorC再到colorD,然后再回到colorA,这需要基于以毫秒为单位的时间,任何帮助将非常感激(算法,伪代码将是伟大的)。
请注意,我正在使用RGB,它可以是0-255或0.0-1.0范围。
这是我目前所做的,我需要改变每一个"timePeriod"的颜色,然后我计算经过的时间百分比并改变颜色,这段代码的问题是当它从a到B再到B到C时有一个跳跃,等等
int millisNow = ofGetElapsedTimeMillis();
int millisSinceLastCheck = millisNow - lastTimeCheck;
if ( millisSinceLastCheck > timePeriod ) {
lastTimeCheck = millisNow;
millisSinceLastCheck = 0;
colorsIndex++;
if ( colorsIndex == colors.size()-1 ) colorsIndex = 0;
cout << "color indes: " << colorsIndex << endl;
cout << "color indes: " << colorsIndex + 1 << endl;
}
timeFraction = (float)(millisSinceLastCheck) / (float)(timePeriod);
float p = timeFraction;
colorT.r = colors[colorsIndex].r * p + ( colors[colorsIndex+1].r * ( 1.0 - p ) );
colorT.g = colors[colorsIndex].g * p + ( colors[colorsIndex+1].g * ( 1.0 - p ) );
colorT.b = colors[colorsIndex].b * p + ( colors[colorsIndex+1].b * ( 1.0 - p ) );
colorT.normalize();
Thanks in advance
你的代码大部分是正确的,但你正在做反向插值:即你是插值B->A,然后C->B,然后D->C,等等。这将导致切换颜色时的不连续性。
你应该替换这个:
colorT.r = colors[colorsIndex].r * p + ( colors[colorsIndex+1].r * ( 1.0 - p ) );
:
colorT.r = colors[colorsIndex].r * (1.0 - p) + ( colors[colorsIndex+1].r * p );
,其他行也一样。
另外,正如其他人所说,使用不同于RGB的颜色空间可以提供更好的效果。
有两种处理颜色插值的方法。一个是快速和简单的(你正在做的),另一个稍微慢一点,但在某些情况下看起来更好。
第一个是(x * s) + (y * (1-s))
的明显、简单的方法,它是纯线性插值,顾名思义。然而,在某些颜色对(比如绿色和橙色)上,你会在中间得到一些令人讨厌的颜色(脏棕色)。这是因为你在帮助每个组件(R, G和B),并且有些组合是不愉快的。如果你只需要最基本的lerp,那么这就是你想要的方法,你的代码是正确的。
如果你想要一个更好看但稍微慢一点的效果,你会想要在HSL色彩空间中插入。由于色调,饱和度和亮度都是内插的,所以你可以得到你想要的颜色,并且可以避免大多数难看的颜色。由于颜色通常是在某种轮中绘制的,因此该方法意识到这一点(基本RGB lerp的行为就像它与3条离散的线一起工作)。
要使用HSL lerp,您需要转换RGB值,在结果之间进行lerp,然后再转换回来。这个页面有一些公式,可能是有用的,这一个有PHP代码来处理它。
插入R、G和B组件将生成工作代码。一个缺点是,您生成的步骤不一定看起来相同,即使它们在数学上是相等的。
如果这让你感到困扰,你可以将值从RGB转换为L*a*b*之类的东西(旨在更接近人类感知),对这些值进行插值,然后将每个插值值转换回RGB以供显示
你已经得到的看起来很好,但我想简化一下数学:
int millisNow = ofGetElapsedTimeMillis();
int millisSinceLastCheck = millisNow % timerPeriod;
int colorsIndex = (millisNow / timerPerod) % (colors.size() - 1);
float p = (float)(millisSinceLastCheck) / (float)(timePeriod);
colorT.r = colors[colorsIndex+1].r * p + ( colors[colorsIndex].r * ( 1.0 - p ) );
colorT.g = colors[colorsIndex+1].g * p + ( colors[colorsIndex].g * ( 1.0 - p ) );
colorT.b = colors[colorsIndex+1].b * p + ( colors[colorsIndex].b * ( 1.0 - p ) );
colorT.normalize();
我们正在做一个项目。我们只是单独处理R, G, B值,并根据中间有多少"步骤"从color1过渡到color2。我们有离散值,所以我们有一个查找表的方法,但你可以对浮点做同样的事情,只是动态计算RGB值。
如果你还有问题,我可以贴一些Java代码。
分离三个组件(RBG)并分别插入分别使用经典插值算法。
- 通过样式表仅在QTabWidget中应用文本颜色一个特定选项卡
- 给一个图 G 找到此图中的所有节点 blob,以便 node.color 属性 = 特定颜色
- 访问和更改基于另一个图像的像素颜色-opencv c++
- 在另一个小部件中更改QWidget的背景颜色
- 在圆上找到一个角度的RGB颜色
- 无法更改另一个窗口内窗口的背景颜色
- 在一个 QTableWidget 单元格中显示不同颜色的字符串
- 用一个glDrawArrays命令绘制几个不同颜色的三角形
- 根据OPENCV中一个通道中的一个值,查找最大颜色像素
- Qt:如何制作一个2d插值颜色的字段
- 给定尺寸为 26 * 7 的图像是否有可能在垫子的每一行中包含 78 个单独的颜色值,而另一个可以包含 77
- 在创建窗口(..)之后,如何给窗口一个颜色
- 如何通过代码创建一个简单的MFC统一颜色HICON图标
- 将SDL_Surface Blit到另一个SDL_Surfaces上,然后应用颜色键
- 颜色空间属于哪一个
- 如何画一个椭圆填充一定的颜色
- 改变一个MFC对话框元素的背景颜色
- Qt:在一个int变量,我想保持颜色信息
- 我如何创建一个颜色条(电视测试模式)
- 如何插入一个颜色序列