0

I have got color names such as White, Red, Blue, etc., and I'm trying to get its corresponding hexadecimal representation. For example, if I pass an argument such as White it should return #FFFFFF.

Although it seems simple, there's no straight solution in Java. Following is the code I have tried.

private String getHexaColor (String basicColor /* White */) {
    java.awt.Color color;
    try {
        java.lang.reflect.Field field = Class.forName("java.awt.Color").getField(basicColor.toLowerCase());
        color = (Color) field.get(null);
    } catch (Exception e) {
        color = null; 
    }

    return (color != null) ? String.format("%06x#", color.getRGB() & 0x00FFFFFF).toUpperCase() : ""; //return #FFFFFF
}

Above code is working fine, but I'm looking for a clean and elegant solution if at all available at least in the latest version of Java.

4
  • 1
    This looks like a question for codereview.stackexchange.com Commented Apr 21, 2019 at 0:05
  • I googled some. The best I could find is a S.O. question with the answer being to do just this: stackoverflow.com/questions/2854043/… - there some other options there involving 3rd party solutions. - I would think there would be a list of colors with hex values online somewhere that you could grab and use. Commented Apr 21, 2019 at 1:06
  • What is your universe of possible color names? Commented Apr 21, 2019 at 1:09
  • I found a really exhaustive list of colors and hex values. If it were me, I'd probably wrap some code around that. - rapidtables.com/web/color/RGB_Color.html Commented Apr 21, 2019 at 1:17

2 Answers 2

2

You should use the format string "#%06X" rather than "%06x#". First, it places the # character at the position you actually want, second, it generates an upper case hexadecimal string, removing the need to call toUpperCase() on the result.

But how much does your reflective operation save, compared to an explicit map of values? When I run over all fields of Color, e.g. via

final int constant = Modifier.STATIC | Modifier.FINAL;
Map<String,Integer> m = new HashMap<>();
for(Field f: Color.class.getFields()) try {
    if((f.getModifiers() & constant) == constant && f.getType() == Color.class)
        m.put(f.getName().toLowerCase().replace('_', ' '),
            ((Color)f.get(null)).getRGB() & 0x00FFFFFF);
} catch(ReflectiveOperationException ex) {
    throw new AssertionError(ex);
}
m.forEach((name,rgb) -> System.out.printf("map.put(\"%s\", \"#%06X\");%n", name, rgb));

I get

map.put("magenta", "#FF00FF");
map.put("pink", "#FFAFAF");
map.put("green", "#00FF00");
map.put("black", "#000000");
map.put("yellow", "#FFFF00");
map.put("cyan", "#00FFFF");
map.put("dark gray", "#404040");
map.put("red", "#FF0000");
map.put("orange", "#FFC800");
map.put("gray", "#808080");
map.put("white", "#FFFFFF");
map.put("blue", "#0000FF");
map.put("darkgray", "#404040");
map.put("light gray", "#C0C0C0");
map.put("lightgray", "#C0C0C0");

which is not that big. So, when I copy that output into a new code like

static final Map<String,String> COLOR_CODES;
static {
    Map<String,String> map = new HashMap<>();
    map.put("magenta", "#FF00FF");
    map.put("pink", "#FFAFAF");
    map.put("green", "#00FF00");
    map.put("black", "#000000");
    map.put("yellow", "#FFFF00");
    map.put("cyan", "#00FFFF");
    map.put("dark gray", "#404040");
    map.put("red", "#FF0000");
    map.put("orange", "#FFC800");
    map.put("gray", "#808080");
    map.put("white", "#FFFFFF");
    map.put("blue", "#0000FF");
    map.put("darkgray", "#404040");
    map.put("light gray", "#C0C0C0");
    map.put("lightgray", "#C0C0C0");
    COLOR_CODES = Collections.unmodifiableMap(map);
}
static String getHexaColor(String colorName) {
    return COLOR_CODES.getOrDefault(colorName.toLowerCase(), "");
}

the result is simple and reflection free. Maintenance would be independent of the reflective code that produced this version, as it is simpler to add a new constant to the map than to add a new constant to the java.awt.Color class (to re-run the reflective code).

The only alternative with more flexibility would be to use a properties file, which allows to update the map without recompiling the application. It’s easy to adapt the code above to generate a properties file instead, but on the other hand, there are enough ready-to-use files on the internet with even more colors. E.g., you can copy the VGA based web colors directly from w3.org, whereas this extended list would require an advanced search-and-replace to be brought into the properties format.

Sign up to request clarification or add additional context in comments.

Comments

0

Using Color from OpenFX, one disposes over a method for all web colors.

import javafx.scene.paint.Color;
Color color = Color.web("skyblue");

Result:

0x87cdebff

These exist also as constant fields, so one might use autocompletion. But I like the autocompletion in a CSS/HTML editor.


This is a separate dependency, library. But as of java 9 a modular infrastructure is to be expected, and OpenFX, formerly JavaFX, is unproblematic.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.