I am writing a program where I take an image determine the average red channel, green channel and blue channel present in that image. I take these averages and pass them as parameters to a new color. I then want to add this color to an array. I repeat this process 24 times. The problem I face is that when I get a new color and add it to the array the previous colors get erased. I want to preserve the existing colors in the array and add to the one that hasn't been filled yet. Here is what I have tried.
System.out.println("R: "+ rAvg);
System.out.println("G: "+ gAvg);
System.out.println("B: "+ bAvg);
Color newColor = new Color(rAvg, gAvg, bAvg);
Color[] ColorArr = new Color[24];
for(int i = 0; i < ColorArr.length; i++){
ColorArr[i] = newColor;
}
System.out.println(Arrays.toString(ColorArr));
Here is the output after one color is added to the array
R: 206
G: 0
B: 0
[java.awt.Color[r=206,g=0,b=0],java.awt.Color[r=206,g=0,b=0]
Here is the array after I add a new color.
R: 211
G: 178
B: 230
[java.awt.Color[r=211,g=178,b=230], java.awt.Color[r=211,g=178,b=230]
The last color gets overwritten and replaced with the new color instead of going in the next index and preserving the last. How can I fix this so I preserve the entered colors in the array and place the new color the index after the previous?
You can restructure your code to something like this:
private Color[] colorArray = new Color[24];
private int currentIndex = 0;
public void addColorToArray(int red, int green, int blue) {
colorArray[currentIndex++] = new Color(red, green, blue);
}
public void myMethodThatDoThis24Times() {
addColorToArray(getRedAverage(), getGreenAverage(), getBlueAverage());
addColorToArray(getRedAverage(), getGreenAverage(), getBlueAverage());
...
}
Your logic looks correct. The only thing which you need to take care is creating a new instance of color object every time.
//ColorArr[i] = newColor; // Instead of this
ColorArr[i] = new Color(rAvg, gAvg, bAvg); // Do this for each element in array
You were initially doing Color newColor = new Color(rAvg, gAvg, bAvg); and assign the same newColor instance to all the elements in the ColorArr.
Thus, a single change in the newColor instance was reflecting the change in all its referenced elements in the array.
As #user alayor, rightly suggested to create new instances of Color(rAvg, gAvg, bAvg) with different RGB values.
Related
i'm having trouble trying to sort an ArrayListof Color.
I'm retrieving all the colors from this image
imgRed.jpg
The code i'm using:
public static ArrayList<Color> getColors(BufferedImage img){
int height = img.getHeight();
int width = img.getWidth();
boolean found = false;
ArrayList<Color> List = new ArrayList<>();
for(int x=0;x<width;x++) {
for(int y=0;y<height;y++) {
found = false;
Color color = new Color(img.getRGB(x, y));
for(Color c : List) {
if(color.getRGB()<c.getRGB()+100 && color.getRGB()>c.getRGB()-100) {
found=true;
}
}
if(!found) {
List.add(color);
}
}
}
return List;
}
After i've collected all the colors, i sort them:
Collections.sort(Colors, Comparator.comparing(Color::getRed)
.thenComparing(Color::getGreen)
.thenComparing(Color::getBlue));
Subsequently i create a new image containing all the colors sorted:
public static void createImage(ArrayList<Color> Colors) {
int width=500;
int height=Colors.size()*10;
BufferedImage b_img = new BufferedImage(width,height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = b_img.createGraphics();
int partialHeight = 0;
int amount = Colors.size();
for(Color c : Colors) {
System.out.println("Colors remaining: "+amount);
graphics.setPaint ( c );
graphics.fillRect ( 0, partialHeight, b_img.getWidth(), partialHeight+10 );
partialHeight = partialHeight + 10;
amount--;
}
File outFile = new File("C:/test/img/out/testColor/outputRed4.png");
try {
ImageIO.write(b_img, "png", outFile);
} catch (IOException e) {
e.printStackTrace();
}
}
This function produces this image: outputRed.png
As you can see, the colors are not really sorted. This is because (i think) colors are sorted basing its numeric value (Red, Green, Blue) and because the RGB numeric value isn't ordered by our perspective.
I remember that the image produced hasn't a color twice so all the color in that image are different.
My question is:
How can i order all the colors following all the shades of each color without having such a jagged result?
Thanks to all
The issue you are encountering comes from the fact that you are taking 3-dimensional data (red values, green values, blue values) and trying to order them in 1 dimension (a List with only an index parameter).
The output you are receiving is most likely exactly what you should expect if you sort first, by the red value of a colour, and then by the green, and then blue. Remember, this method only compares the green value to sort colours with identical red values, and similarly only compares the blue value to sort colours with identical red and blue values.
Perhaps the reason it looks "jagged" is because of the suddenly changing intensity. Given that the input image is pretty much entirely shades of red at different intensities, it might be worth using Comparator.comparing(Color::getTotal) where getTotal() is defined as:
int getTotal() {
return getGreen() + getBlue() + getRed();
}
This will sort by intensity (i.e. brightness), and will make the image look less "jagged", but on images with more than just red, the colours will not be in "colour order" or "rainbow order".
Again, this is an issue of trying to map 3-d data into a 1-d space. Compromises will always have to be made.
How can I print a color in RGB format? I am using Robot(java.awt) to get the color of a random pixel on the screen and I want to print it as RGB. So if the pixel is completely red, the output should be
rgb(255, 0, 0)
Is there something I can do? Should I get the individual red green and blue values(and how can I do that)? Here's what I got so far:
public static void main(String[] args) {
Random rand = new Random();
Robot r = null;
int screenHeight = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
int screenWidth = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
try {
r = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
Color pixelColor = r.getPixelColor(rand.nextInt(screenHeight), rand.nextInt(screenWidth));
System.out.println(pixelColor);
System.exit(0);
}
But it outputs this(random example):
java.awt.Color[r=222,g=228,b=239]
EDIT: I also tried using getRGB() but it still does not work.
//...
Color pixelColor = r.getPixelColor(rand.nextInt(screenHeight), rand.nextInt(screenWidth));
System.out.println(pixelColor.getRGB());
//...
But it outputs(random example):
-723724
What do these numbers mean?
Let's start by having a look at a really simple test
Color color = Color.RED;
System.out.println(color);
System.out.println(color.getRGB());
System.out.println(color.getRed() + ", " + color.getGreen() + ", " + color.getBlue());
Which outputs
java.awt.Color[r=255,g=0,b=0]
-65536
255, 0, 0
The first is the Color objects toString method, which is providing you information about the class and the properties, as you can see, the red property is 255
The second is a integer packed value (the red, green and blue (and alpha) properties all packed into a single int value)
The last is, obviously, each individual property of the color, which would seem to be what you're actually after.
What I think you should do, is go have a read of the JavaDocs on the Color class so you better understand what information it provides, rather then randomly taking stabs at what you think it should provide
I need one small advice on how to set more than one colour to a method setBackgroundColor, i managed to make more than one color but only if program randomly pick color but i want to set specific 4 or five colours,here is my part of the code:
(so on selected object it changes color)
if (isSelected)
style.setBackgroundColor (new Color ((float) Math.random(),
(float) Math.random(),
(float) Math.random()));
else
style.unsetBackgroundColor();
Since you want 4 or 5 specific colors what you could do is make a list.
ArrayList<Color> colorList = new ArrayList<Color>();
//Then you add any colors you want, although you would have to define them yourself.
colorList.add(color1);
After adding the colors to a color list, you would need a way to grab a random color. One way we could do this is by making a Random object and using it to find an Integer from 0 to the list's size.
Random rand = new Random();
int colorNum = rand.nextInt(colorList.size());
Now that we have the actual number, we can simply access that index in the list.
Color c = colorList.get(colorNum);
//Now, assuming your code above works for one color, you could do your
style.setBackgroundColor(c);
This way you can add any colors in or even make colors based on user request and it would handle any color as long as you add it to the list.
The code:
String green = "#99FFCC";
adjustColor(green);
private int adjustColor(String color){
int colorToAdjust = Color.parseColor(color);
//Pseudocode
int red = colorToAdjust.getRed(); //get red value from RGB
red *= 0.5; //halve it
colorToAdjust.setRed(red); //set red value
return colorToAdjust;
}
Given a string hex color, I parse it to an int. How do I change the individual RGB colors? Above is a somewhat pseudo-code of what I'm trying to do: parse hex, get individual color, change it, write it back
You can simply extract the amount of Red by calling red() function and then create the new color based on the original values of Blue & Green and the halved value of the Red you extracted before.
You can then create the new color by calling the rgb() function and passing it the new values of Red, Green & Blue.
Here is the code snippet:
String green = "#99FFCC";
adjustColor(green);
private int adjustColor(String color) {
/* Get RGB Value Of Color */
int colorToAdjust = Color.parseColor(color);
/* Get Red Value From RGB */
int redAmount = Color.red(colorToAdjust);
/* Return New Color By Halving Red */
return Color.rgb(0.5 * redAmount, Color.green(colorToAdjust),
Color.blue(colorToAdjust));
}
You can have a look at this Reference for more information.
I have VARCHAR in the database for colors. The format is rrr,ggg,bbb (example 225,225,0).
How can I convert that String into java.awt.Color and visualize it in a JSF page?
Do this :
1. Read you color column value
2. Split your string values with , or any other separator you have used
3. Parse each value to Integer value
4. Passed this value into java.awt.color constructors.
Sample Example :
int red,green,blue;
String colorStr = "225,225,0"; //Value from DB
String[] ar_color = colorStr.split(",");
red = Integer.parseInt(ar_color[0]);
green = Integer.parseInt(ar_color[1]);
blue = Integer.parseInt(ar_color[2]);
Color myColor = new Color(red, green, blue);
I would parse the database entry and cast the values to integers, then you can use one of the constructors for a java.awt.color.
However I am not sure that is what you want. You want to use this color value in one of your JSF pages.
You might be setting a color on a component like this :
this.myComponent.setStyle("color:'225,225,0'");
So you could dynamically then change the color like this from the DB :
this.myComponent.setStyle("color:" + myColorStringFromDB);
No need to convert to a java color.
Create a Color object, using the values you have
Color color = new Color(int rrr, int ggg, int bbb)
Example
Color color = new Color(255, 255, 0)