cuber
cuber

Reputation: 371

How to sort a color array in Java

I have an made of colors. What I am trying to do is to sort the array from lowest in RGB colors to highest in RGB colors. I tried using Arrays.sort() but its not a comparable that Arrays.sort() can handle. How can I do this?

System.out.println("anchors unsorted: " + Arrays.toString(allAnchorColors));
Arrays.sort(allAnchorColors);
System.out.print("anchors sorted: " + Arrays.toString(allAnchorColors));

output:

anchors unsorted: [java.awt.Color[r=255,g=186,b=34], java.awt.Color[r=255,g=14,b=20], java.awt.Color[r=2,g=255,b=168], java.awt.Color[r=242,g=231,b=255], java.awt.Color[r=255,g=26,b=28], java.awt.Color[r=0,g=65,b=255]]

Upvotes: 1

Views: 4705

Answers (3)

Stuart Wilson
Stuart Wilson

Reputation: 99

This isn't the only way to solve the problem but it's pehaps the most direct. Transform each color into HSV space and then order them by Hue (H). See this page for an explanation and demonstration. An algorithm to go from RGB to HSV is given on this page. Something like this

public class RGBtoHSV {
  float r;
  float g;
  float b;
  public RGBtoHSV(int red, int green, int blue) {
    //Scale to float from 8 bit RGB values
    r = red/255;
    g = green/255;
    b = blue/255;
  }
  public int[] getHSV() {
    float cmax = Math.max(r, Math.max(g, b));
    float cmin = Math.min(r, Math.min(g, b));
    float deltaC = cmax - cmin;
    float h;
    if (cmax==r) {
        h = (((g-b)/deltaC)%6)*60;
    } else if (cmax==g) {
        h = (((b-r)/deltaC) + 2)*60;
    } else {
      h = (((r-g)/deltaC) + 4)*60;
    }
    float s = 0;
    if (cmax!=0) {
      s = deltaC/cmax;
    }
    int[] returnValue = new int[3];
    // re-scale
    returnValue[0] = (int) h/255;
    returnValue[1] = (int) s/255;
    returnValue[2] = (int) cmax/255;
    return returnValue;
}

With the integer h value, choose a starting point h value (as with the cheese wedge in the first link). Then increment (or decrement) mod 256 to get them in order.

Upvotes: 0

MadProgrammer
MadProgrammer

Reputation: 347184

The question is not an easy one to answer directly because Color is made up of at least three primary properties (not including alpha ;)), but indirectly, you need to supply a custom Comparator which can sort the colors based on your requirements, for example.

This basically makes use of the getRGB method which converts the value into a packed int value, making the comparison simpler

Color[] colors = {Color.RED, Color.GREEN, Color.BLUE, Color.BLACK, Color.WHITE};
for (Color color: colors) {
    System.out.println(color.getRGB() + "; " + color);
}

Arrays.sort(colors, new Comparator<Color>() {
    @Override
    public int compare(Color o1, Color o2) {
        return o1.getRGB() - o2.getRGB();
    }
});
System.out.println("After");
for (Color color: colors) {
    System.out.println(color.getRGB() + "; " + color);
}

Which prints out...

-65536; java.awt.Color[r=255,g=0,b=0]
-16711936; java.awt.Color[r=0,g=255,b=0]
-16776961; java.awt.Color[r=0,g=0,b=255]
-16777216; java.awt.Color[r=0,g=0,b=0]
-1; java.awt.Color[r=255,g=255,b=255]
After
-16777216; java.awt.Color[r=0,g=0,b=0]
-16776961; java.awt.Color[r=0,g=0,b=255]
-16711936; java.awt.Color[r=0,g=255,b=0]
-65536; java.awt.Color[r=255,g=0,b=0]
-1; java.awt.Color[r=255,g=255,b=255]

This "kind of" meets your requirements, in the fact that BLACK is before WHITE :P

However, the answer remains the same, you need to supply a custom Comparator which generates the required result when comparing two values based on your algorithm for sorting

I am looking at this but am a little confused because when I implemented what you had here I got a bunch of other colors which I didn't have before

Based on the available information you've been able to provide me, the sort algorithm isn't adding any new values...

Color[] allAnchorColors = {
    new Color(255, 200, 63),
    new Color(255, 8, 12),
    new Color(0, 255, 148),
    new Color(223, 214, 255),
    new Color(255, 19, 19),
    new Color(0, 76, 255),
};
System.out.println("anchors.length = " + allAnchorColors.length);
System.out.println("anchors unsorted: " + Arrays.toString(allAnchorColors));
Arrays.sort(allAnchorColors, new Comparator<Color>() {
    @Override
    public int compare(Color o1, Color o2) {
        return o1.getRGB() - o2.getRGB();
    }
});
System.out.println("anchors.length = " + allAnchorColors.length);
System.out.print("anchors sorted: " + Arrays.toString(allAnchorColors));

Which outputs...

anchors.length = 6
anchors unsorted: [java.awt.Color[r=255,g=200,b=63], java.awt.Color[r=255,g=8,b=12], java.awt.Color[r=0,g=255,b=148], java.awt.Color[r=223,g=214,b=255], java.awt.Color[r=255,g=19,b=19], java.awt.Color[r=0,g=76,b=255]]
anchors.length = 6
anchors sorted: [java.awt.Color[r=0,g=76,b=255], java.awt.Color[r=0,g=255,b=148], java.awt.Color[r=223,g=214,b=255], java.awt.Color[r=255,g=8,b=12], java.awt.Color[r=255,g=19,b=19], java.awt.Color[r=255,g=200,b=63]]BUILD SUCCESSFUL (total time: 4 seconds)

which means, there is something in you code which you're not showing us that's causing the issue

Upvotes: 2

devDeejay
devDeejay

Reputation: 6019

This is how I got the result, Simply sorting them as String values,

        String[] arr = {"java.awt.Color[r=255,g=186,b=34]", "java.awt.Color[r=255,g=14,b=20]", "java.awt.Color[r=2,g=255,b=168]", "java.awt.Color[r=242,g=231,b=255]","java.awt.Color[r=255,g=26,b=28]","java.awt.Color[r=0,g=65,b=255]"};
        java.util.Arrays.sort(arr);
        for (String string : arr) {
            System.out.println(string);
        }

Edit 1:

for (Color color : colorArray) {
    String strColorValue = String.valueOf( color );
    //Make a new arraylist and append strColorValue to it.
    //Sort the list as above.
}

Upvotes: 2

Related Questions