动态创建不同亮度的颜色
Posted
技术标签:
【中文标题】动态创建不同亮度的颜色【英文标题】:Dynamically creating colors with different brightness 【发布时间】:2010-03-01 10:38:19 【问题描述】:我有一种颜色,我只在运行时才知道。使用这种颜色,我想创建两种新颜色,一种非常亮,一种不亮。
所以澄清一下,假设我有红色;我想为“浅红色”颜色和“深红色”颜色创建十六进制值。
我该怎么做呢?我的代码是使用 GWT 用 Java 编写的。
【问题讨论】:
【参考方案1】:将颜色转换为 HSB/HSV(Hue-Saturation-Brightness/Value)空间,将亮度调高调亮,调低调暗。然后再次转换回来。在 Java 中:
import java.awt.Color;
float hsbVals[] = Color.RGBtoHSB( originalColour.getRed(),
originalColour.getGreen(),
originalColour.getBlue(), null );
Color highlight = Color.getHSBColor( hsbVals[0], hsbVals[1], 0.5f * ( 1f + hsbVals[2] ));
Color shadow = Color.getHSBColor( hsbVals[0], hsbVals[1], 0.5f * hsbVals[2] );
HSB 空间就是为这种操作而设计的。
要点是您只需要改变亮度项即可获得所需的变亮/变暗效果。您必须尝试变亮/变暗的程度。
上面的代码将高光的亮度转换为中间的白色,阴影的中间转换为黑色。 (我使用这段代码在按钮上创建了突出显示的边框效果。)
请参阅:http://en.wikipedia.org/wiki/HSL_and_HSV 和 http://www.acasystems.com/en/color-picker/faq-hsb-hsv-color.htm
编辑: 根据 cmets,java.awt.Color
类不能在 GWT 中使用。由于我们使用的Color
类的唯一部分是 HSV 到 RGB 和 RGB 到 HSV 的转换,当你使用 GWT 时,你可以用谷歌搜索这些算法的实现:Google HSV RGB conversion algorithm。例如:
【讨论】:
虽然这个答案已有两年的历史,但我想评论它是错误的。 OP 表示他正在使用 GWT,它不允许使用 AWT 包。使用 java.awt.Color 会导致在构建项目时发生 GWT 错误(不过,eclipse 和开发模式不会出现任何问题)。【参考方案2】:至少有两种不错的解决方案,一种比另一种更好(无论如何更“合适”)。这取决于您要使用颜色的目的,或者与简短代码的权衡。
使用模拟亮度的色彩空间
问题是您的颜色可能被指定为 RGB(即,红色、绿色和蓝色的数量,反映您的显示器。)更改颜色亮度的最佳方法是在亮度为的不同颜色空间中指定颜色一个组件,例如 HSB - 色调(“颜色”)、饱和度(颜色的“数量”)和亮度(不言自明,我认为!)
Wikipedia article on HSL and HSV color models 解释的远比你想知道的要多:)
看看this HSB demo。
关键是,一旦你的颜色被指定在一个不同的空间,其中一个组件是亮度,更改亮度很容易,因为你可以根据需要增加或减少该组件,就像你可以增加或减少数量一样RGB 颜色的蓝色。我认为 Java 内置了一些颜色转换功能 - 一些谷歌搜索发现 this page with a handy example of Color.RGBtoHSB()
并再次返回 Color.HSBtoRGB
。
与白色或黑色混合
这更老套,但在大多数情况下都很有效,而且我编写的大多数代码都需要为不重要的东西(例如 UI 背景)获取两个版本的颜色(例如渐变),都使用这种方法。逻辑是,颜色越接近白色 (RGB 255,255,255) 会更亮,越接近黑色 (RGB 0,0,0) 就会变暗。因此,要使某些东西变亮,请与白色混合,例如 25%。对于每个通道/组件,您可以通过取一种颜色的比例以及另一种颜色的反比例来混合两种颜色。
以下内容未经测试,是我曾经做过同样事情的 Delphi 代码的转换(代码取自内存,除此之外,我已经多年没有使用 Java,也不记得语法和类很好,所以我不希望它编译但你应该能够得到一个想法):
Color Blend(Color clOne, Color clTwo, float fAmount)
float fInverse = 1.0 - fAmount;
// I had to look up getting colour components in java. Google is good :)
float afOne[] = new float[3];
clOne.getColorComponents(afOne);
float afTwo[] = new float[3];
clTwo.getColorComponents(afTwo);
float afResult[] = new float[3];
afResult[0] = afOne[0] * fAmount + afTwo[0] * fInverse;
afResult[1] = afOne[1] * fAmount + afTwo[1] * fInverse;
afResult[2] = afOne[2] * fAmount + afTwo[2] * fInverse;
return new Color (afResult[0], afResult[1], afResult[2]);
你可能会这样使用它:
Color clBrighter = Blend(Color.red, Color.white, 0.25);
您可能想要添加一些安全代码,例如确保每个组件的钳位在 0..255 之间,或者检查 dAmount
是否确实在 0..1 范围内。
Java Color documentation 看起来像 Color
类有各种有用的方法。 (编辑:我刚刚注意到您说您使用的是gwt
而不是awt
- 我没有使用它,也不知道标准Java 中包含哪些类。无论如何,这应该为您指明正确的方向。)可能这不是 Java 中最简洁的方法——这可能是由于我现在对类和方法缺乏了解——但这应该足以让你走上正轨。希望对您有所帮助!
【讨论】:
这是我一直在寻找的完美解决方案。我在问自己,为什么这个答案没有得到更多的支持。第二个参数 clTwo 我硬编码为 Color.white 修复。所以我正在使用混合(myColor,因子);闪电的系数在 0.0 和 1.0 之间。完美的。谢谢。【参考方案3】:我不知道你有哪种格式的颜色(我试图看看 GWT 是否使用颜色......但它们严重依赖 CSS,所以它们没有特定的属性)。
无论如何,如果每个组件(红色、绿色、蓝色)都有一个值,并且每个值的范围在 0 到 255 之间 - 这是标准 - 然后应用此算法:
对于每个组件 将原始值乘以一个因子(比如说 1.1,亮度增加 10%) 将 float/double 值转换为 int 如果此值超过 255,则将其削减为 255然后你会有一个新的颜色(一个新的三元组)。
六色
如果您有网页格式的颜色:
RRGGBB
RR - two hexa digits for red
GG - two hexa digits for green
BB - two hexa digits for blue
您需要将它们转换为 int 并返回到 hexa:
十六进制字符串到 int
Integer.parseInt("AB", 16"); // returns 171
int 到 Hexa 字符串
Integer.toHexaString(171); // returns "AB"
【讨论】:
【参考方案4】:由于您使用的是 GWT,因此您应该使用 HSL 而不是 RGB 进行颜色计算,因为它更直观,并且可以作为样式颜色直接应用于您的组件。
您的初始颜色是“红色”,定义为“color: hsl(0,100%, 50%)”,有关样式颜色的更多信息,请参阅http://www.w3.org/TR/css3-color/#hsl-color。
要获得浅红色,您只需增加 L(亮度)分量,因此浅红色将是“颜色:hsl(0,100%, 75%)”。要获得深红色,请减小 L 分量,“color: hsl(0,100%, 25%)”
要应用您的颜色,只需使用设置颜色
component.getElement().getStyle().setColor("hsl(0,100%, 25%)")
【讨论】:
【参考方案5】:只需将以下函数添加到您的代码中。它将根据您的要求返回浅色和深色的哈希值。
传递两个参数。 (1) 您选择的颜色的哈希值。 (2)你想要多少更亮或更暗(例如,如果你想要 10% 更亮的阴影然后传递 0.1 作为第二个参数,如果你想要 40% 更暗然后传递 -0.4(更暗的负值)作为第二个参数)
因此,如果您想找到 20% 较浅的红色阴影,请拨打以下电话String lightred=convert("ff0000",0.2);
public static String convert(String hex, double num)
String rgb = "#",temp;
int i;
double c,cd;
for (i = 0; i < 3; i++)
c = Integer.parseInt(hex.substring(i * 2,(i*2)+2), 16);
c = Math.min(Math.max(0, c+(255*num)), 255);
cd=c-(int)c;
if(cd>0)c=(int)c+1;
temp = Integer.toHexString((int)c);
if(temp.length()<2)
temp=temp+temp;
rgb += temp;
return rgb;
【讨论】:
以上是关于动态创建不同亮度的颜色的主要内容,如果未能解决你的问题,请参考以下文章