Color Sorting In PHP: Part 2

23rd June 2018

Following on from my last post about sorting colors I have been thinking about different ways of sorting colors. I have been looking at interfaces that allow people to select colors and they will quite normally have a band of colors that does look nicely sorted. As it turns out this is perfectly possible to do if the colors are normalised to remove light and dark variations of different colors.

The easiest way to remove different amounts of lightness and darkness from a color is to convert it to the HSV color space. This way we can just set the value (brightness) and saturation (amount of grey) to be 1. This will change the color by simply removing any information that does not pertain to the actual color. For example, a color that is a very light shade of blue will be changed to be simply blue.

I already have a function that converts a color from RGB to HSV from my previous post. All we need to do is create another function that does the opposite. Here is a function that takes HSV color values and returns the RGB values.

  1. function hsvToRbg($hue, $saturation, $value) {
  2. $chroma = $value * $saturation;
  3.  
  4. $hue_value = $hue / 60.0;
  5.  
  6. $x = $chroma * (1 - abs(fmod($hue_value, 2) - 1));
  7.  
  8. $match = $value - $chroma;
  9.  
  10. if ($hue_value >= 0 && $hue_value < 1) {
  11. $red = $chroma;
  12. $green = $x;
  13. $blue = 0;
  14. } else {
  15. if ($hue_value >= 1 && $hue_value < 2) {
  16. $red = $x;
  17. $green = $chroma;
  18. $blue = 0;
  19. } else {
  20. if ($hue_value >= 2 && $hue_value < 3) {
  21. $red = 0;
  22. $green = $chroma;
  23. $blue = $x;
  24. } else {
  25. if ($hue_value >= 3 && $hue_value < 4) {
  26. $red = 0;
  27. $green = $x;
  28. $blue = $chroma;
  29. } else {
  30. if ($hue_value >= 4 && $hue_value < 5) {
  31. $red = $x;
  32. $green = 0;
  33. $blue = $chroma;
  34. } else {
  35. $red = $chroma;
  36. $green = 0;
  37. $blue = $x;
  38. }
  39. }
  40. }
  41. }
  42. }
  43.  
  44. $red = round(($red + $match) * 255);
  45. $green = round(($green + $match) * 255);
  46. $blue = round(($blue + $match) * 255);
  47.  
  48. return ['red' => $red, 'green' => $green, 'blue' => $blue];
  49. }

With this in hand we can now normalise the color array. This is the same random array of colors that I created in the previous post. We just need to loop through each of the colors we have and force the saturation and hue to be 1.

  1. foreach ($colors as $color) {
  2. $hsv = rgbTohsv($color);
  3.  
  4. $hsv['saturation'] = 1;
  5. $hsv['value'] = 1;
  6. $colorRgb = hsvToRbg($hsv['hue'], $hsv['saturation'], $hsv['value']);
  7.  
  8. $color->red = $colorRgb['red'];
  9. $color->green = $colorRgb['green'];
  10. $color->blue = $colorRgb['blue'];
  11. }

With that done we can now sort the array of colors by hue.

  1. usort($colors, function ($a, $b) {
  2. $aHsv = rgbTohsv($a);
  3. $bHsv = rgbTohsv($b);
  4.  
  5. $aValue = $aHsv['hue'];
  6. $bValue = $bHsv['hue'];
  7.  
  8. return $aValue <=> $bValue;
  9. });

Here is the output of our new sort.

Colors sorted by normalised hue.

As you can see we now have a lovely looking band of colors that is obviously sorted.

The only issue here is that in order to do this we have lost information. By changing the colors in this way we are essentially throwing away two thirds of the information in the original array. Colors like white and black and also completely missing. This is not entirely ideal, but this is perhaps the only way to represent the complex information contained in an array of colors.

Add new comment

The content of this field is kept private and will not be shown publicly.