Parsing a "rgb (x, x, x)" String Into a Color Object

14,242

Solution 1

As far as I know there's nothing like this built-in to Java or GWT. You'll have to code your own method:

public static Color parse(String input) 
{
    Pattern c = Pattern.compile("rgb *\\( *([0-9]+), *([0-9]+), *([0-9]+) *\\)");
    Matcher m = c.matcher(input);

    if (m.matches()) 
    {
        return new Color(Integer.valueOf(m.group(1)),  // r
                         Integer.valueOf(m.group(2)),  // g
                         Integer.valueOf(m.group(3))); // b 
    }

    return null;  
}

You can use that like this

// java.awt.Color[r=128,g=32,b=212]
System.out.println(parse("rgb(128,32,212)"));     

// java.awt.Color[r=255,g=0,b=255]                         
System.out.println(parse("rgb (255, 0, 255)"));   

// throws IllegalArgumentException: 
// Color parameter outside of expected range: Red Blue
System.out.println(parse("rgb (256, 1, 300)"));  

Solution 2

For those of use who don't understand regex:

public class Test
{
    public static void main(String args[]) throws Exception
    {
        String text = "rgb(255,0,0)";
        String[] colors = text.substring(4, text.length() - 1 ).split(",");
        Color color = new Color(
            Integer.parseInt(colors[0].trim()),
            Integer.parseInt(colors[1].trim()),
            Integer.parseInt(colors[2].trim())
            );
        System.out.println( color );
    }

}

Edit: I knew someone would comment on error checking. I was leaving that up to the poster. It is easily handled by doing:

if (text.startsWith("rgb(") && text.endsWith(")"))
   // do the parsing
   if (colors.length == 3)
      // build and return the color

return null;

The point is your don't need a complicated regex that nobody understands at first glance. Adding error conditions is a simple task.

Solution 3

I still prefer the regex solution (and voted accordingly) but camickr does make a point that regex is a bit obscure, especially to kids today who haven't used Unix (when it was a manly-man's operating system with only a command line interface -- Booyah!!). So here is a high-level solution that I'm offering up, not because I think it's better, but because it acts as an example of how to use some the nifty Guava functions:

package com.stevej;

import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;

public class StackOverflowMain {

  public static void main(String[] args) {

    Splitter extractParams = Splitter.on("rgb").omitEmptyStrings().trimResults();

    Splitter splitParams =
        Splitter.on(CharMatcher.anyOf("(),").or(CharMatcher.WHITESPACE)).omitEmptyStrings()
            .trimResults();

    final String test1 = "rgb(11,44,88)";

    System.out.println("test1");
    for (String param : splitParams.split(Iterables.getOnlyElement(extractParams.split(test1)))) {
      System.out.println("param: [" + param + "]");
    }

    final String test2 = "rgb      ( 111,         444         , 888         )";

    System.out.println("test2");
    for (String param : splitParams.split(Iterables.getOnlyElement(extractParams.split(test2)))) {
      System.out.println("param: [" + param + "]");
    }

  }
}

Output:

test1
param: [11]
param: [44]
param: [88]
test2
param: [111]
param: [444]
param: [888]

It's regex-ee-ish without the regex.

It is left as an exercise to the reader to add checks that (a) "rgb" appears in the beginning of the string, (b) the parentheses are balanced and correctly positioned, and (c) the correct number of correctly formatted rgb integers are returned.

Share:
14,242

Related videos on Youtube

monksy
Author by

monksy

Personal Website: http://stevenkhicks.de

Updated on June 05, 2022

Comments

  • monksy
    monksy almost 2 years

    Is there an effecient way/existing solution for parsing the string "rgb (x, x, x)" [where x in this case is 0-255] into a color object? [I'm planning to use the color values to convert them into the hex color equivilience.

    I would prefer there to be a GWT option for this. I also realize that it would be easy to use something like Scanner.nextInt. However I was looking for a more reliable manner to get this information.

  • monksy
    monksy over 12 years
    This isn't a very good solution because it assumes that the incoming string will always be in the format that you expect. Additionally it assumes that you'll always get 3 back, from it. [which is the reason why I wanted to avoid using Scanner]
  • Steve J
    Steve J over 12 years
    camickr, I have to side on monksy on this one. Regex is the right tool for the job, and the point of a forum like stackoverflow is for less experienced programmers and engineers to study the solutions offered up by more experienced programmers and engineers, and in doing so, become more experienced in the process. Thankfully the voting mechanism will help direct people to the "right" solution -- that is, the one that is likely to offer them not only the desired behaviour but also the chance to learn something new, and in this case, broadly useful. My two cents.
  • monksy
    monksy over 12 years
    Camic performance wise you're right. However fexibility and readabilty suffer with this approach. I'm not gooing to downvote this because it is a valid solution.
  • NullUserException
    NullUserException over 12 years
    The regex looks like bad because it allows for an arbitrary number of spaces and everything has to be double-escaped in Java, but it's a much cleaner solution IMO. I've edited it; now it should look better.
  • camickr
    camickr over 12 years
    Most programming is spent maintaining code. Therefore code should be easy to understand and maintain. Unless you actually know something about Regex, there is no way anybody could understand that code. On that basis my code is more readable. Regex is not the solution for everthing. Just look at the number of postings on the forum asking for Regex help. Most people don't understand them. Even beginners understand "if statements". If there are no other alternative then sure use a Regex, but I just provided a simple alternative.
  • camickr
    camickr over 12 years
    @NullUserExceptionఠ_ఠ and everything has to be double-escaped in Java another reason why Regex is confusing to anyone but the experienced. @Steve j, all the voting was done before my suggestion was posted. Since then even the popular answer has been updated because of the overly complicated Regex, which just goes to prove my point. You don't have write an edit of a text value in a single line of code.
  • Steve J
    Steve J over 12 years
    camickr, I see your point. I've offered up a high-level solution using easy-to-read and easy-to-understand Guava classes and methods. I'd like to know if you think it strikes the right balance between elegance and efficiency and clarity.
  • monksy
    monksy over 12 years
    @camickr well if you are having to maintain code, someone shouldn't be modifying bits of code they don't understand. You wouldn't throw a neophyte at a RegExp and tell them "fix it"
  • camickr
    camickr over 12 years
    @monksy, that is my point, even you are suggesting that a neophyte should not fix a Regex. That is because they can be confusing and hard to understand. Yes, there are problems where a Regex is the better solution. I just don't believe you need for force a Regex for every solution. Why would a manager want to pay a "specialist" top dollar to code/recode a Regex when the same code can easily be done another way? I find too many people get addicted to Regex without considering the alternatives and maintenance issues.