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
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.
i wrote a java code to change all the red values of a black and white image to 255, so the output would be a red image.
But its not red, instead it outputs a brighter image.
What did I do wrong?
File bwgFile = new File("X:/Java/Documents/NetBeansProjects/colour/input/bwg.png");
BufferedImage bwgImage = ImageIO.read(bwgFile);
int width=bwgImage.getWidth();
int height=bwgImage.getHeight();
for(int w=0; w<width; w++){
for(int h=0; h<height; h++){
int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
int c=bwg.getRed();
Color red = new Color(255,c,c);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);
}
}
ImageIO.write(bwgImage, "png", new File("X:/Java/Documents/NetBeansProjects/colour/output/c.png"));
input
output
EDIT:
I have found out what the problem was, apparently when the input is a greyscale image it will try to make the output a greyscale image as well thus making it darker when blue and green colors get removed and brighter when red gets added. not using a grayscale image as input fixed it.
If I understand what you're trying to do, you're trying to create a greyscale image, except that it is "redscale", using only shades of red. Therefore, you need to compute the greyscale constant of each pixel.
From wikipedia (Greyscale), the luminance of a pixel Y = 0.2126R + 0.7152G + 0.0722B. So, try this
int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
float c = (0.2126f * bwg.getRed() + 0.7152f * bwg.getGreen() + 0.0722f * bwg.getBlue());
int cc = (int)Math.round(c);
Color red = new Color(cc, 0, 0);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);
Alternatively, you can simply retain the red component and set green and blue to 0. This will leave you with just the "redness" of each pixel.
int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
int c=bwg.getRed();
Color red = new Color(c,0,0);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);
NOTE: This solution above only works on images that are not using IndexColorModel. You can check the color model using BufferedImage's getColorModel(). For IndexColorModel, setRGB() does not work directly and instead picks a color in the index closest to the set color, as per HaraldK's comment. To achieve the desired result for images using IndexColorModel, you can create a new BufferedImage with TYPE_INT_ARGB:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Then, write the calculated pixel colors to this new image and save the new image instead.
I'm trying to take a screenshot and then look through it for a pixel that has a certain color. Firstly, I tried to just print the color of an image at a certain xy coordinate but I could not even do that. What am I doing wrong?
static int ScreenWidth;
static int ScreenHeight;
static Robot robot;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic
callibrateScreenSize();
findSquares();
//takeScreenShot();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void callibrateScreenSize() {
try {
Rectangle captureSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
ScreenWidth = captureSize.width;
ScreenHeight = captureSize.height;
System.out.println("Width is " + ScreenWidth);
System.out.println("Height is " + ScreenHeight);
} catch (Exception e) {
e.printStackTrace();
}
//return null;
}
public static BufferedImage takeScreenShot() {
Rectangle captureSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage image = robot.createScreenCapture(captureSize);
return image;
}
public static void findSquares() {
System.out.println(takeScreenShot().getRGB(5,5));
}
Thanks!
You can use BufferedImage#getRGB or byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData() to get the pixel data. getRBG is more convenient, but is typically slower than getting the pixel array
getRGB packs the pixel data into an int, getData will return the RGB(A) in each entry of the array (R = n; G = n+1; B=n+2(, A=n+3)), so will need to process this yourself
You can use java.awt.Color, which allows you to access the RGB values of the color, pack it as a int value or convert an int to a Color
Color color = new Color(bufferedImage.getRGB(0, 0), true);
int redColor = Color.RED.getRGB();
The answer to this question provides an example of dealing with the byte[] pixel data
Basically, you will need to loop over the data, comparing the values in the image to the value you are after, either directly (comparing the red, green and blue values) or indirectly, comparing the packed int or Color values.
Personally, I'd grab the pixel data, convert each element to an int and compare it with a previously packed int from a Color object, this creates the less number of short lived objects and should be reasonably efficient
You can take a look at this answer which use getRGB to get the red, green, blue values from a given pixel
Here's something I wrote a while ago using the Robot class. It returns an array of the screen wherever the screen is white, it was not very computationally expensive for my application, but I found probing the values individually using robot was. At first I didn't even read your question, but looking back, I think this will help you A LOT. Good luck. And then I saw the original post date...
public boolean[][] raster() throws AWTException, IOException{
boolean[][] filled= new boolean[720][480];
BufferedImage image = new Robot().createScreenCapture(new Rectangle(0,0,720,480));
//accepts (xCoord,yCoord, width, height) of screen
for (int n =0; n<720; n++){
for (int m=0; m<480; m++){
if(new Color(image.getRGB(n, m)).getRed()<254){
//can check any rgb value, I just chose red in this case to check for white pixels
filled[n][m]=true;
}
}
}
return filled;
}
I am trying to figure out how to make my game draw a certain tile in a specific spot using an image to represent each spot. So if a pixel of that image was the color red a specified picture(tile) would be draw in the game, and each pixel that was green stood for a different specified image. I have seen people who make games do this but I dont know how to do it and I dont know the name for it.
If you need more info I can try to explain what I want to do more. Could someone please help?
That may actually be slower in the long run. I would definitely recommend you use a byte array to represent the tiles, i.e. byte[width][height]. It will be faster, easier to manage and easier to extend to something like spriteData[width][height] if a single byte does not supply enough information anymore.
However, if you insist on using an image to store game data, you can use something like the following:
File file = new File("mygamedata.jpg");
BufferedImage image = ImageIO.read(file);
// Getting pixel color at position x, y (width, height)
int colour = image.getRGB(x ,y);
int red = (colour & 0x00ff0000) >> 16;
int green = (colour & 0x0000ff00) >> 8;
int blue = colour & 0x000000ff;
System.out.println("Red colour component = " + red);
System.out.println("Green colour component = " + green);
System.out.println("Blue colour component = " + blue);
Each component will be in the range (0...255) and you can use that to determine the correct tile, i.e.
Graphics2D gfx = (Graphics2D) offScreenImage.getImage();
if (red == 120 && green == 0 && blue == 0) {
gc.drawImage(tile[whichTileYouWantForRed], x, y, null); // where x and y is the pixel you read.
}
Alternatively, you can skip extracting the components altogether, and simply use colour, i.e.
if (colour == 0x00ff0000) {
gc.drawImage(tile[whichTileYouWantForRed], x, y, null); // where x and y is the pixel you read.
}
(Which will be slightly faster anyway and actually what you want.)
I've tried to create colored gray image with given colour but I always failed. I know I have to use BufferedImage and load all pixels of source image into array, but I don't know how to work with color value, so there always were some weird colors after multiplying source color and given color (for the record I've got code to get int of color).
Thanks for any help.
e.g. http://dl.dropbox.com/u/17664230/ruka.png
Are you trying to change image gray channel (white-black) to (some_color-black) ?
public void recolor(BufferedImage source, BufferedImage destination, int color) {
WritableRaster destinationRaster = destination.getRaster();
Raster sourceRaster = source.getRaster();
//red, green, blue
int channels = new int[]{color & 0xFF0000, color & 0xFF00, color & 0xFF};
for (int channel=0; channel<3; channel++){
for (int y=0; y<sourceRaster.getHeight(); y++) {
for (int x=0; x<rangeSlicer.getWidth(); x++) {
pixel = sourceRaster.getSample(x, y, channel);
pixel = Math.round((double)pixel/255.0 * channels[channel]);
destinationRaster.setSample(x, y, channel, pixel);
}
}
}
}
Not sure if this compiles, but idea is that. For more effective program check RescaleOp.
I would define some alpha = 0.2 and do:
given gray #777777
make redder with:
new red = 77 * (1.0 + alpha)
new green = blue = 77 * (1.0 - alpha)
Actually, you have to be careful and make sure to truncate (1 + alpha) and (1 - alpha) such that you only use values between 0 and 1.0.
Use Math.min(0.0, 1.0 - alpha) instead of (1.0 - alpha) and Math.max(1.0, 1.0 + alpha) instead of (1.0 + alpha).
With this formula, if you are given black (#000000), it stays black. If you are given white (#FFFFFF), it ends up pink (#FFCCCC). If you set alpha = 1.0, white would end up pure red (#FF0000).
You could come up with different color scaling formulas, but I guess you should make sure that your transformation always keeps black as pure black.