我正在寻找用于将 RGBA、HSL 和 HSLA 颜色转换为 RGB 颜色的算法的描述,或用于将它们转换为 java.awt.Color 对象的库。
你能帮助我吗?
使用评论中的新信息,我将对其进行更改以反映您拥有的内容与您需要的内容。
首先,我们需要解析 rgb/hsl 字符串。这可以很容易地使用几个正则表达式和String.split
:
private static final Pattern hexRegex = Pattern.compile("#[\\dA-Fa-f]{6}");
private static final Pattern rgbRegex = Pattern.compile("rgba?\\([^)]*\\)", Pattern.CASE_INSENSITIVE);
private static final Pattern hlsRegex = Pattern.compile("hlsa?\\([^)]*\\)", Pattern.CASE_INSENSITIVE);
第一个Pattern
匹配任何十六进制编码的值。第二个匹配rgb(something)
或rgba(something)
。第三个与第二个相同,但带有hsl
and hsla
。要使用这些:
public static int[] getRGB(String cssString) {
if (hexRegex.matcher(cssString).matches())
return getRgbFromHex(cssString);
if (rgbRegex.matcher(cssString).matches())
return getRgbFromRgb(cssString);
if (hslRegex.matcher(cssString).matches())
return getRgbFromHsl(cssString);
return null; // no match
}
private static int[] getRgbFromHex(String hexString) {
int rgb = Integer.decode(hexString);
Color c = new Color(rgb);
return new int[] { c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha() };
}
private static int[] getRgbFromRgb(String rgbString) {
String[] values = rgbString.split("[\\s,()]");
// values[0] is just "rgb" or "rgba"
String red = values[1];
String green = values[2];
String blue = values[3];
String alpha = "1.0";
if (values.length >= 5) {
alpha = values[4];
}
return new int[] {
parseValue(red, 255),
parseValue(green, 255),
parseValue(blue, 255),
parseAlpha(alpha),
};
}
private static int[] getRgbFromHsl(String hslString) {
String[] values = hslString.split("[\\s,()]");
// values[0] is just "hsl" or "hsla"
String hue = values[1];
String sat = values[2];
String light = values[3];
String alpha = "1.0";
if (values.length >= 5) {
alpha = values[4];
}
int h = parseValue(hue, 360);
double s = parsePercent(sat);
double l = parsePercent(light);
int a = parseAlpha(alpha);
return hslToRgb(h, s, l, a);
}
private static int[] hslToRgb(int h, double s, double l, int a) {
// TODO Calculate me
int r = 0;
int g = 0;
int b = 0;
return new int[] { r, g, b, a };
}
private static int parseValue(String val, int max) {
if (val.endsWith("%")) {
return (int) (parsePercent(val) * max);
}
return Integer.parseInt(val);
}
private static double parsePercent(String perc) {
return Integer.parseInt(perc.substring(0, perc.length() - 1)) / 100.0;
}
private static int parseAlpha(String alpha) {
return (int) (Double.parseDouble(alpha) * 255);
}
这就是一切:
getRGB
- 获取 CSS 字符串,确定其格式,然后继续解析它。null
如果无法确定格式(即无效)则返回。返回的数组将是 4 个元素,r、g、b 和 a,所有值都在 0 到 255 之间。getRgbFromHex
- 用于Integer.decode
解析它,因为它#
为我们生成十六进制数字,然后用于Color
获取 RGB 值。getRgbFromRgb
- 解析rgb
字符串中的值(包括rgba
)。在空格、逗号或括号上拆分字符串,然后解析每个单独的值并从中创建一个数组。getRgbFromHsl
- 行为类似于getRgbFromRgb
,但使用 HSL 值和适当的解析而不是 RGB 解析。hslToRgb
- 这是您在评论中说您已经完成的计算逻辑。只需在int
这里从 h、s 和 l 计算 r、g 和 b 的值,这种方法就行了。parseValue
- 如果是百分比,则返回解析后的百分比乘以 的值max
,否则,它只是将其解析为int
using Integer.parseInt
。parsePercent
- 解析字符串的整数部分并返回double
除以 100 的值。parseAlpha
- 将 alpha 解析为 adouble
并返回 255 次。使用 rgb/rgba 进行测试确认这是可行的:
public static void main(String[] args) {
System.out.println(Arrays.toString(getRGB("#FF00CC")));
System.out.println(Arrays.toString(getRGB("rgb(255,0,0)")));
System.out.println(Arrays.toString(getRGB("rgba(255,0,0,0.5)")));
System.out.println(Arrays.toString(getRGB("rgba(100%,0%,30%,0.5)")));
}
这打印:
[255, 0, 204, 255]
[255, 0, 0, 255]
[255, 0, 0, 127]
[255, 0, 76, 127]
您可能要考虑的另一件事是使用舍入而不是直接转换int
为百分比内容。这将提高百分比的准确性。
如果您还有其他问题,请告诉我。
您可以使用Color.HSBtoRGB
和Color.RGBtoHSB
。例如:
int r = 0, g = 255, b = 255;
float[] hsb = Color.RGBtoHSB(r, g, b, null);
for (float f : hsb) {
System.out.println(f);
}
这输出:
0.5
1.0
1.0
这三个float
值分别是 H、S 和 B 值。对于带有 alpha 的颜色,alpha 不会从 RGB 变为 HSB,因此A == A
.
Color
使用返回的数组创建一个:
Color color = Color.getHSBColor(hsb[0], hsb[1], hsb[2]);
如果没有更多关于您到底想要什么作为输入和输出的详细信息,我无法为您提供更多帮助。
编辑:请参阅我的其他答案。
您的正则表达式规则无法正常工作,因为它们允许不正确的字符串(例如 "rgba(1000,500%,500%,2)" )并拒绝正确的形式(例如 "#fff" )。
我写了更严格和正确的正则表达式规则:
String keywords_color_regex = "^[a-z]*$";
String hex_color_regex = "^#[0-9a-f]{3}([0-9a-f]{3})?$";
String rgb_color_regex = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$";
String rgba_color_regex = "^rgba\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*((0.[1-9])|[01])\\s*\\)$";
String hsl_color_regex = "^hsl\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*\\)$";
对于 rgba 和 hsla,我的目标是计算实际显示的颜色。所以我想知道,给定一个 rgba/hsla 颜色及其背景颜色,是否有一种方法可以“混合”它们来计算显示的颜色......