Search code examples
flutterdartsortingcolors

Sort a list of colors by hue (Dart)


I have a list of 8-bit ARGB integer colors. It looks like this.

List<int> listOfColors = [-2350809, -5980676, -8722497, -2380289, -30596, -272549, -18312];

I want to display this colors in a list sorted by hue. Means for eg. all red color tones (from dark to light) should be displayed one below the other, then the green color tones, then the blue color tones...

How can i achieve this? I tried to convert the colors to hsv but i can´t figure out how to sort them.

var hsvColor = HSVColor.fromColor(Color(colorInt));

Can someone point me in the right direction?


Solution

  • Here you have a sample of how you can sort by hue.

      static List<int> sortColorsByHue(List<int> colors) {
        List<Map<String, dynamic>> colorsWithHue = [];
    
        // Calculate hue for each color
        for (int color in colors) {
          List<double> hsv = argbToHsv(color);
          colorsWithHue.add({'color': color, 'hue': hsv[0]});
        }
    
        // Sort colors based on hue
        colorsWithHue
            .sort((a, b) => (a['hue'] as double).compareTo(b['hue'] as double));
    
        // Extract sorted colors
        List<int> sortedColors = [];
        for (var colorData in colorsWithHue) {
          sortedColors.add(colorData['color'] as int);
        }
    
        return sortedColors;
      }
    
    
      // Convert ARGB to HSV
      static List<double> argbToHsv(int argb) {
        double r = ((argb >> 16) & 0xFF) / 255.0;
        double g = ((argb >> 8) & 0xFF) / 255.0;
        double b = (argb & 0xFF) / 255.0;
    
        double maxChannelValue = max(max(r, g), b);
        double minChannelValue = min(min(r, g), b);
        double delta = maxChannelValue - minChannelValue;
    
        double h, s;
        double v = maxChannelValue;
    
        if (delta == 0) {
          h = 0;
          s = 0;
        } else {
          s = delta / maxChannelValue;
    
          if (r == maxChannelValue) {
            h = (g - b) / delta;
          } else if (g == maxChannelValue) {
            h = 2 + (b - r) / delta;
          } else {
            h = 4 + (r - g) / delta;
          }
    
          h *= 60;
          if (h < 0) h += 360;
        }
    
        return [h, s, v];
      }
    

    let me know if it works for you.