Colour Sorting In PHP: Part 2

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

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

I already have a function that converts a colour 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 colour values and returns the RGB values.

function hsvToRbg($hue, $saturation, $value) {
  $chroma = $value * $saturation;

  $hue_value = $hue / 60.0;

  $x = $chroma * (1 - abs(fmod($hue_value, 2) - 1));

  $match = $value - $chroma;

  if ($hue_value >= 0 && $hue_value < 1) {
      $red = $chroma;
      $green = $x;
      $blue = 0;
  } else {
      if ($hue_value >= 1 && $hue_value < 2) {
          $red = $x;
          $green = $chroma;
          $blue = 0;
      } else {
          if ($hue_value >= 2 && $hue_value < 3) {
              $red = 0;
              $green = $chroma;
              $blue = $x;
          } else {
              if ($hue_value >= 3 && $hue_value < 4) {
                  $red = 0;
                  $green = $x;
                  $blue = $chroma;
              } else {
                  if ($hue_value >= 4 && $hue_value < 5) {
                      $red = $x;
                      $green = 0;
                      $blue = $chroma;
                  } else {
                      $red = $chroma;
                      $green = 0;
                      $blue = $x;
                  }
              }
          }
      }
  }

  $red = round(($red + $match) * 255);
  $green = round(($green + $match) * 255);
  $blue = round(($blue + $match) * 255);

  return ['red' => $red, 'green' => $green, 'blue' => $blue];
}

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

foreach ($colours as $colour) {
  $hsv = rgbTohsv($colour);

  $hsv['saturation'] = 1;
  $hsv['value'] = 1;
  $colourRgb = hsvToRbg($hsv['hue'], $hsv['saturation'], $hsv['value']);

  $colour->red = $colourRgb['red'];
  $colour->green = $colourRgb['green'];
  $colour->blue = $colourRgb['blue'];
}

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

usort($colours, function ($a, $b) {
  $aHsv = rgbTohsv($a);
  $bHsv = rgbTohsv($b);

  $aValue = $aHsv['hue'];
  $bValue = $bHsv['hue'];

  return $aValue <=> $bValue;
});

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 colours that is obviously sorted.

The only issue here is that in order to do this we have lost information. By changing the colours in this way we are essentially throwing away two thirds of the information in the original array. Colours 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 colours.

More in this series

Add new comment

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