I want to make a negative of an image in Java, but I'm not sure how to convert a Color object into an array which can be manipulated. Here's a snippet of my code:
Color col;
col = picture.getPixel(x,y).getColor();
//x and y are from a for loop
picture.getPixel(x,y).setColor(~~~);
setColor takes three integers, one for each color channel RBG. I want to convert Color col to an array which I can read. Something like the below:
picture.getPixel(x,y).setColor(255-col[0],255-col[1],255-col[2]);
255-col[n] of course creates a negative of the pixel, but Color col is not an array when I'd like to access it as one. How can I cast a Color object as an array?
I could do something like the below and not use a Color object at all,
r = picture.getPixel(x,y).getRed(); //r is now an integer 0-255
//repeat the above for green and blue
picture.getPixel(x,y).setColor(r,g,b);
But I'd much rather do it in one line.
What about :
int [] arrayRGB = new int[3];
arrayRGB[0] = col.getRed();
arrayRGB[1] = col.getGreen();
arrayRGB[2] = col.getBlue();
Or directly :
picture.getPixel(x,y).setColor(255-col.getRed(),255-col.getGreen(),255-col.getBlue());
Take a look at the Color class.
You cannot cast Color as an array, but you can get it's components as an array:
int[] rgb = new int[] { col.getRed(), col.getGreen(), col.getBlue() };
You might want to just use these directly.
Related
I have a Collection of Integers of Processing colors (it contains colors of images rescaled to 1x1 to get the "average" color).
I have this thing that must retrieve me the nearest color of the array :
public static int getNearestColor(Collection<Integer> colors, int color) {
return colors.stream()
.min(Comparator.comparingInt(i -> Math.abs(i - color)))
.orElseThrow(() -> new NoSuchElementException("No value present"));
}
But when I do this, it returns me a color that is way far than the input, but the array contains some colors that are nearest than the input, this is my problem that I don't understand ?
The RGB color channels of a color() are encoded in an int. You can extract the red, green and blue component of the color, by red(), green() and blue().
Treat the color channels as a 3 dimensional vector (PVector) and compute the Euclidean distance of 2 color vectors, by dist(). The color with the shortest "distance" is the "nearest" color:
In the following function the arguments c1 and c2 are colors of type int:
float ColorDistance(int c1, int c2) {
return PVector.dist(
new PVector(red(c1), green(c1), blue(c1)),
new PVector(red(c2), green(c2), blue(c2)));
}
Find the "nearest" color, in a collection of colors, by finding the minimum floating point "distance" (ColorDistance(i, color)).
arrays in java don't have a stream method; perhaps you meant Arrays.stream(colors). IntStream has no way to do a comparison other than on natural order. You can map to the difference (abs(i - color)) first, but now you've deleted the information you were looking for (the original color), so that won't work either. Let's box it. This results in the following code, which is exactly like your code, except this compiles and runs. I'll then also add a test case to make it a self-contained example:
int[] colors = {1,4,5,9,12};
int target = 6;
int a = Arrays.stream(colors).boxed()
.min(Comparator.comparingInt(i -> Math.abs(i - target)))
.orElseThrow(() -> new NoSuchElementException());
System.out.println(a);
and, whoa nelly, '5' falls out, which is exactly what you want.
In other words, the intent of your code is fine, if it's not giving the right answer your inputs are not what you thought they are, or something else is wrong that cannot be gleaned from your paste.
May I suggest that if it is at all possible to put the question in a simple, self contained form (as this question clearly was, see the code snippet in this answer), that you do so? Often you'll answer your own questions that way :)
public static int getNearestColor(int[] colors, int color) {
int minDiff = IntStream.of(colors)
.map(val -> Math.abs(val - color))
.min()
.getAsInt();
OptionalInt num = IntStream.of(colors)
.filter(val-> val==(color + minDiff))
.findFirst();
if(num.isPresent()){
return color + minDiff;
} else {
return color - minDiff;
}
}
I am working on a program where I am trying to avoid more than one red color specifically (255,0,0). To add some variation and make it less likely to occur that I get (255,0,0) What I tried to do was this, but I am having trouble assigning the random variable to the specific color channel. How can I do this?
int x = rand.nextInt(1) + 8;
if(color.getRed() == 255 && color.getBlue() == 0 && color.getGreen() == 0){
color.getBlue() = x;
color.getGreen() = x;
}
The statement
color.getBlue() = x;
makes no sense. It's the same as trying to say "0 = x;".
If color references an object of a class that allows you to change its color channels, you should try:
color.setBlue(x);
However, if color is a java.awt.Color, this won't work because java.awt.Color is immutable. Your only choice then would be to create a new Color object like this:
color = new Color(255, x, x);
First of all
color.getBlue() = ...
is illegal. You cannot assign to a function call
Second, to help you with your question: I recommend that rather than randomly generating a list of colors out of the whole range of RGB, create a few preset colors, put them into an array, and then create random colors by getting random indexes into your color array
I'm trying to wrap my head around three-dimensional arrays. I understand that they are arrays of two-dimensional arrays, but the book I'm reading said something that confuses me.
In an exercise for the book I'm reading, it asks me to make a three-dimensional array for a full-color image. It gives a small example saying this:
If we decide to choose a three-dimensional array, here's how the array might be declared:
int[][][] colorImage = new int[numRows][numColumns][3];
However, wouldn't it be more effective like this?
int[][][] colorImage = new int[3][numRows][numColumns];
Where 3 is the rgb values, 0 being red, 1 being green, and 2 being blue. With the latter, each two-dimensional array would be storing the color value of the row and column, right? I just want to make sure I understand how to effectively use a three-dimensional array.
Any help will be greatly appreciated, thanks.
Order doesn't matter, and in fact the former form is more readable:
final const int RED = 0;
final const int GREEN = 1;
final const int BLUE = 2;
int[][][] colorImage = new int[numRows][numColumns][3];
//...
int x = getSomeX();
int y = getSomeY();
int redComponent = colorImage[x][y][RED];
int greenComponent = colorImage[x][y][GREEN];
int blueComponent = colorImage[x][y][BLUE];
The order shouldn't matter, so one isn't more effective than the other. The only thing that matters is that whatever accesses colorImage knows which dimension is used for what. Bit more context on multidimensional arrays here.
I'm not sure if its a good idea to put everything in an 3dimensional array of int.
Your first mistake is the dataytpe:
RGB is a int.
But R is a byte, G is a byte, B is a byte too.. (Color.getXXX() delivers an int, I dont know why because its a byte 0-255)
You need an int because you want to address more than 256 cols&rows. (Thats okay).
But i think that its much better to encapsulate the color information in a extra object. Perhaps a private datastructure like
class MyColor {
public byte r, g, b; //public for efficient access;
public int color; //public for efficient access;
public MyColor(final int rgb) {
this(new Color(rgb));
}
public MyColor(final Color c) {
this((byte) c.getRed(), (byte) c.getGreen(), (byte) c.getBlue(), c.getRGB());
}
public MyColor(final byte red, final byte green, final byte blue, final int c) {
this.r = red;
this.g = green;
this.b = blue;
this.color = c;
}
}
and put this in an 2dim array of MyColor[numRows][numColumns]
But if you make the class MyColor public to your whole app - i would change the design of the class to be more secure.
I have an image with TYPE_3BYTE_BGR and I want to convert it to a TYPE_INT_RGB.
Though I have searched, I have not found a method to do this. I want to convert the image pixel by pixel. However, it seems that BufferedImage.getRGB(i, j) doesn't work.
How can I get the RGB values in an image of type TYPE_3BYTE_BGR?
I'm not sure what you mean by "getRGB(i,j) doesn't work". getRGB returns a packed int; you need to decode it.
int color = image.getRGB(i,j);
int r = (argb)&0xFF;
int g = (argb>>8)&0xFF;
int b = (argb>>16)&0xFF;
int a = (argb>>24)&0xFF;
See How to convert get.rgb(x,y) integer pixel to Color(r,g,b,a) in Java?
I need a bit of a hand reading the buffer that is spat out by the glReadPixels feature in android's opengl-es api. Here is my code so far...
public static void pick(GL11 gl){
int[] viewport = new int[4];
IntBuffer pixel = IntBuffer.allocate(384000);
mColourR = BaseObject.getColourR();
mColourG = BaseObject.getColourG();
mColourB = BaseObject.getColourB();
x = MGLSurfaceView.X();
y = MGLSurfaceView.Y();
gl.glGetIntegerv(GL11.GL_VIEWPORT,viewport,0);
gl.glReadPixels((int)x,viewport[3]-(int)y, 1, 1, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixel);
}
the name of the output buffer in this code is "pixel" what do I need to add to this code to get the colour values back from the "pixel" buffer.
You can use one of the get() methods of the IntBuffer to access individual values.
RGB color values are usually stored in that very order, so calling pixel.get(0) will get you the red value of the first pixel, pixel.get(1) will get you the green channel and so on. Usually, the values are stored line-wise.
So, if you need a value for a particular pixel, (x,y) you will have to call get(screenWidth*3*y + x)
By the way, you can retrieve the raw int array from your IntBufferby calling pixels.array()