Convert colour names to RGB values in Java - java

I want an RGB value when the colour name is given as input. The following code is working for some colors (I guess for primary colors like red) and failing for some others (like cyan and mauve):
import java.awt.Color;
import javax.swing.text.html.StyleSheet;
public class ColourTest {
public static void main(String[] args) {
StyleSheet s = new StyleSheet();
String colourName = "RED";
Color clr = s.stringToColor(colourName);
int r = clr.getRed();
int g = clr.getGreen();
int b = clr.getBlue();
System.out.println("red:" + r + " green :" + g + " blue:" + b);
}
}
Is there another way to get the RGB values for the color names?

Here's what I have found in the javax.swing.text.html.CSS class:
/**
* Convert a color string such as "RED" or "#NNNNNN" or "rgb(r, g, b)"
* to a Color.
*/
static Color stringToColor(String str) {
Color color;
if (str == null) {
return null;
}
if (str.length() == 0)
color = Color.black;
else if (str.startsWith("rgb(")) {
color = parseRGB(str);
}
else if (str.charAt(0) == '#')
color = hexToColor(str);
else if (str.equalsIgnoreCase("Black"))
color = hexToColor("#000000");
else if(str.equalsIgnoreCase("Silver"))
color = hexToColor("#C0C0C0");
else if(str.equalsIgnoreCase("Gray"))
color = hexToColor("#808080");
else if(str.equalsIgnoreCase("White"))
color = hexToColor("#FFFFFF");
else if(str.equalsIgnoreCase("Maroon"))
color = hexToColor("#800000");
else if(str.equalsIgnoreCase("Red"))
color = hexToColor("#FF0000");
else if(str.equalsIgnoreCase("Purple"))
color = hexToColor("#800080");
else if(str.equalsIgnoreCase("Fuchsia"))
color = hexToColor("#FF00FF");
else if(str.equalsIgnoreCase("Green"))
color = hexToColor("#008000");
else if(str.equalsIgnoreCase("Lime"))
color = hexToColor("#00FF00");
else if(str.equalsIgnoreCase("Olive"))
color = hexToColor("#808000");
else if(str.equalsIgnoreCase("Yellow"))
color = hexToColor("#FFFF00");
else if(str.equalsIgnoreCase("Navy"))
color = hexToColor("#000080");
else if(str.equalsIgnoreCase("Blue"))
color = hexToColor("#0000FF");
else if(str.equalsIgnoreCase("Teal"))
color = hexToColor("#008080");
else if(str.equalsIgnoreCase("Aqua"))
color = hexToColor("#00FFFF");
else if(str.equalsIgnoreCase("Orange"))
color = hexToColor("#FF8000");
else
color = hexToColor(str); // sometimes get specified without leading #
return color;
}
Thus if you are passing any color which is not present in the code above, you will unfortunately get a NullPointerException
However, I have found a hack to solve your problem. Use this code:
public static void main(String[] args) {
StyleSheet s = new StyleSheet();
String colourName = "Cyan";
Color clr = stringToColorCustom(colourName);
int r = clr.getRed();
int g = clr.getGreen();
int b = clr.getBlue();
System.out.println("red:" + r + " green :" + g + " blue:" + b);
}
static Color stringToColorCustom(String str) {
Color color;
if (str == null) {
return null;
}
if (str.length() == 0)
color = Color.black;
else if (str.charAt(0) == '#')
color = hexToColor(str);
else if (str.equalsIgnoreCase("Black"))
color = hexToColor("#000000");
else if (str.equalsIgnoreCase("Silver"))
color = hexToColor("#C0C0C0");
else if (str.equalsIgnoreCase("Gray"))
color = hexToColor("#808080");
else if (str.equalsIgnoreCase("White"))
color = hexToColor("#FFFFFF");
else if (str.equalsIgnoreCase("Maroon"))
color = hexToColor("#800000");
else if (str.equalsIgnoreCase("Red"))
color = hexToColor("#FF0000");
else if (str.equalsIgnoreCase("Purple"))
color = hexToColor("#800080");
else if (str.equalsIgnoreCase("Fuchsia"))
color = hexToColor("#FF00FF");
else if (str.equalsIgnoreCase("Green"))
color = hexToColor("#008000");
else if (str.equalsIgnoreCase("Lime"))
color = hexToColor("#00FF00");
else if (str.equalsIgnoreCase("Olive"))
color = hexToColor("#808000");
else if (str.equalsIgnoreCase("Yellow"))
color = hexToColor("#FFFF00");
else if (str.equalsIgnoreCase("Navy"))
color = hexToColor("#000080");
else if (str.equalsIgnoreCase("Blue"))
color = hexToColor("#0000FF");
else if (str.equalsIgnoreCase("Teal"))
color = hexToColor("#008080");
else if (str.equalsIgnoreCase("Aqua"))
color = hexToColor("#00FFFF");
else if (str.equalsIgnoreCase("Orange"))
color = hexToColor("#FF8000");
else if (str.equalsIgnoreCase("Cyan")) // Add your color
color = hexToColor("#00FFFF"); // Add the RGB
else
color = hexToColor(str); // Sometimes get specified
// without a leading #
return color;
}
static final Color hexToColor(String value) {
String digits;
int n = value.length();
if (value.startsWith("#")) {
digits = value.substring(1, Math.min(value.length(), 7));
}
else {
digits = value;
}
String hstr = "0x" + digits;
Color c;
try {
c = Color.decode(hstr);
}
catch (NumberFormatException nfe) {
c = null;
}
return c;
}
In the above code I have created a custom stringToColorCustom method, and now I can add whatever colors I want in that method.

I suggest to use the kind of a translation table via HashMap:
HashMap<NamedColor, RgbColor> table = new HashMap<>();
table.put(new NamedColor("red"), new RgbColor("#ff0000"));
table.put(new NamedColor("blue"), new RgbColor("#0000ff"));
How the conversion works:
class ColorConverter {
// If you need reverse color conversion you can use handy bidirectoinal
// maps from http://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/bidimap/DualHashBidiMap.html
private HashMap<Color, RgbColor> table;
public static RgbColor convert(NamedColor color) {
return table.get(color);
}
Adjust this outline to your needs.

Easiest in javafx:
import javafx.scene.paint.Color;
Color color = Color.web("orange");
System.out.printf("Color: %s, RGBA #%x%n", color, color.hashCode());
For java.awt.Color one can use (slow) reflection on all those constants define there:
private static Optional<java.awt.Color> color(String name) {
try {
Field field = java.awt.Color.class.getDeclaredField(name.toUpperCase());
int modifiers = field.getModifiers();
if (field.getType() == java.awt.Color.class && Modifier.isStatic(modifiers
&& Modifier.isPublic(modifiers))) {
return Optional.of((java.awt.Color)field.get(null));
}
} catch (NoSuchFieldException e) {
}
return Optional.empty();
}
Here there are some problems with names using underscore (which were removed in javafx).
System.out.println("RGBA " + color("orange")
.map(c -> String.format("#%x", c.getRGB()))
.orElse("(unknown)"));
Because of CSS support in java's HTML with color names, there should exist an other solution, but I have never sought.

Related

I was asked to write a code that returns a rectangle that blocks any given polygon between 3 and 10 points (java+arrays+loops)

what the method needs to do: to put it simply, we receive any number of points(from class Point) like (1,4)...(7,2) and there can be anywhere from 3 to 10 (if less then 3 it returns null) and the methods needs to return the rectangle(which needs to be from class Polygon) that blocks the Polygon created from the given points, (in other words we get points that create a polygon and we need to find the rectangle that blocks the polygon),
the problem: I believe the code i created should work? but my main problem is I don't know how to write the return command to return those values that are from class Point and print them in this method which is supposed to be class Polygon, I have a toString command that prints out everything i just don't know how can i take those point values from SW,SE,NE,NW and insert return them with toString inside the getBoundingBox() method
Thanks if you can help i will add the code below, the method i am having trouble with in the return command is public Polygon getBoundingBox()
//tester
Polygon boundingBox = polygon.getBoundingBox();
String boundingBoxStr = boundingBox.toString();
if (boundingBoxStr.equals("The polygon has 4 vertices:\n((1,0),(7,0),(7,6),(1,6))"))
System.out.println("\ngetBoundingBox - OK");
else
{
System.out.println("\nError in getBoundingBox or in toString");
System.out.println("Your bounding box is:\n" + boundingBox + "\nExpected bounding box is:\nThe polygon has 4 vertices:\n((1,0),(7,0),(7,6),(1,6))");
}
// instance variables -
private Point [] _vertices;
private int _noOfVertices;
private final int MAX_VERTICES = 10;
// constructor
public Polygon()
{
_vertices = new Point[MAX_VERTICES];
_noOfVertices = 0;
}
// add vertex(or point)
public boolean addVertex(int x, int y)
{
if (_noOfVertices == MAX_VERTICES)
return false;
_vertices[_noOfVertices++] = new Point(x,y);
return true;
}
//toString
public String toString()
{
String str = "";
if(_noOfVertices == 0)
{
str = "The polygon has 0 vertices.";
}
int i;
if(_noOfVertices > 0)
{
str += "The polygon has " + _noOfVertices + " vertices:" + "\n";
str += "" + ("(");
for(i=0; i < _noOfVertices; i++)
if (i == _noOfVertices-1)
{
str += "" + _vertices[i];
}
else
{
str += "" + _vertices[i] + ",";
}
if(i ==_noOfVertices)
{
str += "" + (")");
}
}
return str;
}
public Polygon getBoundingBox()
{
Polygon rectangle = new Polygon();
String str = "";
if(_noOfVertices < 3)
return null;
Point SW = _vertices[0];
Point SE = _vertices[0];
Point NE = _vertices[0];
Point NW = _vertices[0];
for (int i=1; i<_noOfVertices; i++)
{
if(_vertices[i].isLeft(SW) && _vertices[i].isUnder(SW))
{
SW = _vertices[i];
}
if(_vertices[i].isRight(SE) && _vertices[i].isUnder(SE))
{
SE = _vertices[i];
}
if(_vertices[i].isRight(NE) && _vertices[i].isAbove(NE))
{
NE = _vertices[i];
}
if(_vertices[i].isLeft(NW) && _vertices[i].isAbove(NW))
{
NW = _vertices[i];
}
}
return new Polygon(SW,SE,NE,NW); // if i try to add the points SW,SE,NE,NW to Polygon i get an error "constructor polygon in class polygon can't be
// to given types
// I am suppsoed to print it out like this using toString command:
// The polygon has 5 vertices:
// ((SW,SE,NE,NW))
}

MPandroidChart) How to apply two colors to setFillColor

example
What I've tried.
Please help me.. I really don't know.
I think it's related to canvas class.
CustomLineChartRenderer
It seems to me that color is not filled according to x value, but color is filled at once.
It's hard because I'm not used to canvas. Please help me.
Here are three methods for drawing lines and filling in colors.
#Override
protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, XBounds bounds) {
final Path filled = mGenerateFilledPathBuffer;
final int startingIndex = bounds.min;
final int endingIndex = bounds.range + bounds.min;
final int indexInterval = 128;
int currentStartIndex = 0;
int currentEndIndex = indexInterval;
int iterations = 0;
// Doing this iteratively in order to avoid OutOfMemory errors that can happen on large bounds sets.
do {
currentStartIndex = startingIndex + (iterations * indexInterval);
currentEndIndex = currentStartIndex + indexInterval;
currentEndIndex = currentEndIndex > endingIndex ? endingIndex : currentEndIndex;
if (currentStartIndex <= currentEndIndex) {
generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled);
trans.pathValueToPixel(filled);
final Drawable drawable = dataSet.getFillDrawable();
if (drawable != null) {
drawFilledPath(c, filled, drawable);
} else {
//////Here part of applying color
drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha());
}
}
iterations++;
} while (currentStartIndex <= currentEndIndex);
}
#Override
protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fillAlpha) {
int color = (fillAlpha << 24) | (fillColor & 0xffffff);
if (clipPathSupported()) {
Log.e("clipPathSupported","1");
int save = c.save();
c.clipPath(filledPath);
c.drawColor(color);
c.restoreToCount(save);
} else {
Log.e("clipPathSupported","2");
// save
Paint.Style previous = mRenderPaint.getStyle();
int previousColor = mRenderPaint.getColor();
// set
mRenderPaint.setStyle(Paint.Style.FILL);
mRenderPaint.setColor(color);
c.drawPath(filledPath, mRenderPaint);
// restore
mRenderPaint.setColor(previousColor);
mRenderPaint.setStyle(previous);
}
}
private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) {
final float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart);
final float phaseY = mAnimator.getPhaseY();
final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED;
final Path filled = outputPath;
filled.reset();
final Entry entry = dataSet.getEntryForIndex(startIndex);
filled.moveTo(entry.getX(), fillMin);
filled.lineTo(entry.getX(), entry.getY() * phaseY);
// create a new path
Entry currentEntry = null;
Entry previousEntry = entry;
for (int x = startIndex + 1; x <= endIndex; x++) {
currentEntry = dataSet.getEntryForIndex(x);
if (isDrawSteppedEnabled) {
filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY);
}
filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY);
previousEntry = currentEntry;
}
// close up
if (currentEntry != null) {
filled.lineTo(currentEntry.getX(), fillMin);
}
filled.close();
}
You can use shader, same :
mRenderPaint.shader = LinearGradient(fromX, fromY, toX, toY, color1,
color2,
Shader.TileMode.CLAMP)

Find contrast difference between two colors

I've got a method that sets the text and images tints of a parent to some color. Now if the background of the parent and the foreground (the tint I'm settings) are close in contrast the text won't be readable.
How can I check for the difference between those 2 colors and change one (make it lighter or darker) up to a point where they become readable?
Here's what I've got till now:
public static void invokeContrastSafety(ViewGroup parent, int tint, boolean shouldPreserveForeground) {
Drawable background = parent.getBackground();
if (background instanceof ColorDrawable) {
if (isColorDark(((ColorDrawable) background).getColor())) {
// Parent background is dark
if (isColorDark(tint)) {
// Tint (foreground) color is also dark.
if (shouldPreserveForeground) {
// We can't modify tint color, changing background to make things readable.
} else {
// Altering foreground to make things readable
}
invokeInternal(parent, tint);
} else {
// Everything is readable. Just pass it on.
invokeInternal(parent, tint);
}
} else {
// Parent background is light
if (!isColorDark(tint)) {
if (shouldPreserveForeground) {
} else {
}
} else {
invokeInternal(parent, tint);
}
}
}
}
private static boolean isColorDark(int color){
double darkness = 1-(0.299* Color.red(color) + 0.587*Color.green(color) + 0.114*Color.blue(color))/255;
return darkness >= 0.2;
}
Try this one it works for me. This function returns that the color is dark or light.
public static boolean isBrightColor(int color) {
if (android.R.color.transparent == color)
return true;
boolean rtnValue = false;
int[] rgb = { Color.red(color), Color.green(color), Color.blue(color) };
int brightness = (int) Math.sqrt(rgb[0] * rgb[0] * .241 + rgb[1]
* rgb[1] * .691 + rgb[2] * rgb[2] * .068);
// Color is Light
if (brightness >= 200) {
rtnValue = true;
}
return rtnValue;
}
You can change your custom logic in this function if you need.

setTextColor depending on random String from array - Android

I have a String array with color names and an array with colors:
String[] words = new String[] {"yellow", "white", "green"};
int[] colors = new int[] {Color.YELLOW, Color.WHITE, Color.GREEN};
My TextView is set to one of these words randomly and now I want to set the text color to yellow if yellow was chosen, etc. I tried this with an if statement, but it keeps showing only black words.
1) Retrieve the word that the TextView has:
String chosenWord = String.valueOf(yourTextView.getText());
2) Get the chosenWord position in words:
int position = Arrays.asList(words).indexOf(chosenWord);
3) Get the corresponding color:
int newColor = Color.BLACK;
if(position > -1) {
newColor = colors[position];
}
yourTextView.setTextColor(newColor);
For all the ways to change a TextView color check this.
BTW, do you know Map? You can use them in this cases when you need to map a key with an specific value.
you could use a model object for it. E.g.
public class MyColor {
public String mColorName;
public int mColor;
public MyColor (String name, int color) {
mColorName = name;
mColor = color;
}
}
and then declare your array like
MyColor[] color = new MyColor[] { new MyColor("yellow", Color.YELLOW), new MyColor("white", Color.WHITE), new MyColor("green", Color.GREEN) };
This way you can easily access the name associated to the color
With this way you have one array and easier to manage.
public class MyColor {
public String name;
public int code;
public MyColor(String n, int c) {
this.name = n;
this.code = c;
}
}
ArrayList<MyColor> colors = new ArrayList<>();
colors.add(new MyColor("black", Color.BLACK));
colors.add(new MyColor("yellow", Color.YELLOW));
colors.add(new MyColor("green", Color.GREEN));
for (MyColor color : colors) {
if(color.name.equals(colorStr)) {
yourTextView.setTextColor(color.name);
}
}
Try this code:
if(tv.getTextColors().getDefaultColor() == colors[0])
tv.setText(words[0]);
else if(tv.getTextColors().getDefaultColor() == colors[1])
tv.setText(words[1]);
else if(tv.getTextColors().getDefaultColor() == colors[2])
tv.setText(words[2]);

Starting and Stopping boolean() function

I'm attemping to use this code from http://www.openprocessing.org/sketch/7050 to make countries formed using the letters from the name of whatever the country is. But I want to make it so once the user presses the right arrow key, the process will start over again, but instead, created a new country and use the letters of that country. I'm a little stuck- what I have makes it so when you press the right arrow key, it begins to make the next country from where ever the previous function left off. Is there a way to make it so it just starts over instead?
PFont font;
String fontpath = "ArialMT-200.vlw";
int fontstart = 300;
int fontend = 8;
float fontsize = fontstart;
float fontsizedecrease = 0.97;
PImage bg;
PImage australia;
String country1 = "australia.jpg";
String country2 = "austria.jpg";
String letters = "Australia";
char[] chars = new char[52];
int nchars = 0;
int iterations = 500;
int c = 0;
PGraphics letter,lettersquare,drawing;
void setup(){
//initialize the sketch
size(900,600);
//background(255);
//initialize the font
//font = loadFont(fontpath);
///*
for(int i=0;i<letters.length();i++){
boolean found = false;
char lc = letters.charAt(i);
for(int j=0;j<nchars;j++){
if(chars[j]==lc){
found = true;
break;
}
}
if(!found) chars[nchars++] = lc;
}
chars = (char[]) subset(chars,0,nchars);
font = createFont("Arial",200,true,chars);
//*/
textAlign(CENTER,CENTER);
//load the image that will be filled with letters
australia = loadImage(country1);
austria = loadImage(country2);
//france = loadImage(country3);
//guatemala = loadImage(country4);
// italy = loadImage(country5);
// japan = loadImage(country6);
bg = loadImage("background.jpg");
//posterize the image
australia.filter(THRESHOLD,0.4);
australia.filter(BLUR,3);
australia.filter(THRESHOLD,0.6);
austria.filter(THRESHOLD,0.4);
austria.filter(BLUR,3);
austria.filter(THRESHOLD,0.6);
//initialize the drawing buffers
letter = createGraphics((int)fontsize,(int)fontsize,JAVA2D);
lettersquare = createGraphics((int)fontsize,(int)fontsize,P2D);
drawing = createGraphics(width,height,JAVA2D);
drawing.beginDraw();
drawing.background(255);
// THIS STUPID THING NEEDS TO GO HERE!!!!
drawing.image(bg,0,0);
drawing.endDraw();
}
void draw(){
background(255);
if(floor(fontsize)>fontend&&c<letters.length()-1){
if(!letterfit()){
fontsize *= fontsizedecrease;
}else{
c++;
if(c==11){
fontsize *= 0.75;
}
}
tint(255);
image(drawing,0,0);
if(mousePressed){
tint(255,100);
image(australia,0,0);
}
}else{
tint(255);
image(drawing,0,0);
println(c+" "+letters.length());
/*
save("mlk-"+hour()+""+minute()+""+second()+".tif");
exit();
*/
noLoop();
}
}
boolean letterfit(){
letter.beginDraw();
letter.background(255,0);
letter.fill(0);
letter.textAlign(CENTER,CENTER);
letter.translate(fontsize/2,fontsize/2);
letter.rotate(random(TWO_PI));
letter.scale(fontsize/fontstart);
letter.textFont(font);
letter.smooth();
letter.text(letters.charAt(c),0,0);
letter.endDraw();
lettersquare.beginDraw();
lettersquare.background(255);
lettersquare.image(letter,0,0);
lettersquare.filter(ERODE);
lettersquare.filter(ERODE);
lettersquare.endDraw();
for(int i=0;i<iterations;i++){
int x = floor(random(width-fontsize));
int y = floor(random(height-fontsize));
boolean fits = true;
for(int dx=0;dx<fontsize&&fits;dx++){
for(int dy=0;dy<fontsize&&fits;dy++){
if(brightness(australia.get(x+dx,y+dy))>127){
fits = false;
break;
}
if(brightness(lettersquare.get(dx,dy))<127){
if(brightness(drawing.get(x+dx,y+dy))<127){
fits = false;
}
}
}
}
if (keyCode == RIGHT) {
for(int dx=0;dx<fontsize&&fits;dx++){
for(int dy=0;dy<fontsize&&fits;dy++){
if(brightness(austria.get(x+dx,y+dy))>127){
fits = false;
break;
}
if(brightness(lettersquare.get(dx,dy))<127){
if(brightness(drawing.get(x+dx,y+dy))<127){
fits = false;
}
}
}
}
if(fits){
drawing.beginDraw();
drawing.image(letter,x,y);
drawing.endDraw();
return true;
}
}
if(fits){
drawing.beginDraw();
drawing.image(letter,x,y);
drawing.endDraw();
return true;
}
}
return false;
}

Categories

Resources