Compare two colors in image? - java

I'm trying to compare the given pixel to Color.BLACK. But the problem is it yields false for all the images. (I made a black image and it also returned false!)
public int isItBlackOrWhite(int x , int y)
{
int c = bimg.getPixel(x, y);
if(c == Color.BLACK)
{System.out.println("Helooo");return 0;}
else
return 1;
}
Also I tried to compare it with Color.White but the application quit and force closed!
public int isItBlackOrWhite(int x , int y)
{
int c = bimg.getPixel(x, y);
if(c == Color.WHITE)
{System.out.println("Helooo");return 0;}
else
return 1;
}
NOTE: bimg is an Bitmap image taken from the camera.

First, use LogCat for printing comments and variables. (Eclipse -> Window -> Show View -> Android -> LogCat.
Then you should see the error in the Log.
That will help us to locate the error.

I don't know the specifics of the pixel formats you're using, but you're trying to compare a 32-bit integer representation of a color (most probably in ARGB format) with an object of type Color. You need to first get the ARGB representation of the Color object (probably by calling Color.getRGB() ) before comparing it to the result of getPixel().

As for the "black" image: you need another test image. Taking a picture with the camera will never get you a truly black photo. So finding truly black pixels will be hard too.
(Just add a debug statement to print the value of c to validate that. For Color.BLACK you should get -16777216, or hexadecimal 0xff000000.)

Color.BLACK is Color but not int. You need to cast them to the same type before comparing.

Ugly solution, but the answers below doesn't give actual solution to your problem. Try this:
Color white = new Color(0,0,0); // for white
Color black = new Color(255,255,255); // for black
if(yourPixel.equals(white)) { // operate }
You can also create a Color Constants class and use it accordingly and I think you can find one from the internet. If you're willing to implement that class, RGB value of colors.

The problem might be your usage of ==, which doesnt quite have the meaning you intend. In java it checks that two objects are the same object, and the color you get from your picture will never be equal to the value recorded in Color.BLACK
What you want to do is check that the color's values are the same, the red, green, blue, and alpha channels. This is a context dependent equality, which is usually implemented as the .equals() function of an object.
Try this one:
c.equals(Color.BLACK)
instead of
c == Color.BLACK

Related

Processing how to get the nearest color from a Collection of colors

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;
}
}

imagej always shows black images

for an assignment I have to display an image using imagej in java. So I used the following code:
FloatProcessor abc=new FloatProcessor(imageSizeX,imageSizeY);
for (int i=0;i<imageSizeX;i++){
for(int j=0;j<imageSizeY;j++){
abc.putPixel(i, j, 100);
}
}
ImagePlus im=new ImagePlus("test",abc);
im.show();
but the Image I get is always completely black. Can you tell me what the mistake is?
It should at least be white if the value was 0 shouldn't it?
(FYI: imageSizeX=imageSizeY=256)
.putPixel uses the conversion Float.intBitsToFloat.
If you want a direct access to the pixels, you can use setf(int x, int y, float value).
Moreover, if you already have the pixels into an array, you can use the constructors to immediately set the pixel values FloatProcessor(int width, int height, int[] pixels).

How to change the value of a color channel

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

NASA Worldwind: How can I change the color of the speed leader for tactical symbols?

In NASA WorldWind, one can assign a "direction of travel" speed leader to the Milstd-2525 symbols. However, this speed leader is black, making it very difficult to see against the dark blue ocean background. I have tried changing the internal color material in the TacticalSymbolAttributes, but this doesn't seem to have an effect (on anything). The documentation unfortunately doesn't provide any clues on how to change the line's color.
Is it possible to change the color of the Milstd-2525 Tactical Symbol's speed leader line in Worldwind, and if so, how?
Base of source codes of WorldWindJava on github, class MilStd2525TacticalSymbol overrides method named layoutDynamicModifiers. In this method you can see that for DIRECTION_OF_MOVEMENT only eventually addLine(...) is called (This method is implemented in the superclass AbstractTacticalSymbol which only adds a line to a list named currentLines) and only SPEED_LEADER_SCALE could be set and other properties for the direction of movement could not be changed externally.
#Override
protected void layoutDynamicModifiers(DrawContext dc, AVList modifiers, OrderedSymbol osym)
{
this.currentLines.clear();
if (!this.isShowGraphicModifiers())
return;
// Direction of Movement indicator. Placed either at the center of the icon or at the bottom of the symbol
// layout.
Object o = this.getModifier(SymbologyConstants.DIRECTION_OF_MOVEMENT);
if (o != null && o instanceof Angle)
{
// The length of the direction of movement line is equal to the height of the symbol frame. See
// MIL-STD-2525C section 5.3.4.1.c, page 33.
double length = this.iconRect.getHeight();
Object d = this.getModifier(SymbologyConstants.SPEED_LEADER_SCALE);
if (d != null && d instanceof Number)
length *= ((Number) d).doubleValue();
if (this.useGroundHeadingIndicator)
{
List<? extends Point2D> points = MilStd2525Util.computeGroundHeadingIndicatorPoints(dc, osym.placePoint,
(Angle) o, length, this.iconRect.getHeight());
this.addLine(dc, Offset.BOTTOM_CENTER, points, LAYOUT_RELATIVE, points.size() - 1, osym);
}
else
{
List<? extends Point2D> points = MilStd2525Util.computeCenterHeadingIndicatorPoints(dc,
osym.placePoint, (Angle) o, length);
this.addLine(dc, Offset.CENTER, points, null, 0, osym);
}
}
}
In the superclass AbstractTacticalSymbol, field currentLines (which contains the line for the direction of movement) is used in a method named drawLines(...) which draws added lines to the mentioned list (line 2366 of class). In line 2364 you can see that color is set to black.
gl.glColor4f(0f, 0f, 0f, opacity.floatValue());
Now I suggest you extend MilStd2525TacticalSymbol and do following:
extend class AbstractTacticalSymbol.Line and define some fields to store color.
override method layoutDynamicModifiers and get your own key (for example DIRECTION_OF_MOVEMENT_COLOR) to get color from modifiers and use this given color to create your own line and add this to currentLines list (you can override method addLine for this purpose).
finally override drawLines to use store color in your own Line class and change the color of gl before draw line (you can change back color to black after the direction of movement is drawn).
I'm running off an earlier Worldwind but try Taking a look at AbstractTacticalSymbol.java -> drawLines() method.
It's defaulting the glColor to black before drawing the lines.

Create color out of RGB gives another color than original RGB

I need to create a Color object out of the RGB color of a pixel (of a BufferedImage object which reads a PNG file, BufferedImage colorspace is BufferedImage.TYPE_4BYTE_ABGR). However on some colors there are problems, please see the code below and the output. I guess it's some kind of colorspace problem, but I don't know how to solve it ): Thanks for any hint!
// imagine some great loop for x,y around the following code
int color = myImage.getRGB(x, y);
Color c = new Color(myImage.getRGB(x, y));
if(c.getRGB() != color)
System.out.println("fail " + color + " vs " + c.getRGB());
Output:
fail -116782582 vs -16119286
fail 0 vs -16777216
fail 117440511 vs -1
fail -1090519040 vs -16777216
fail 1488435127 vs -4737097
fail -1090453247 vs -16711423
and some more. If it helps: e.g. transparency becomes black. I guess the new Color object is using another colorspace than the BufferedImage, but I don't know how to set the colorspace for a new Color object? Or is the RGB information just not enough to recreate the color?
I think the problem is that you are throwing out the alpha information in the color. I think you need to do the following:
int color = myImage.getRGB(x, y);
ColorModel model = myImage.getColorModel();
Color c = new Color(color, model.hasAlpha());

Categories

Resources