code: function(env, op, other) {
          var result = [],
              rgb2;
  
          if (other instanceof tree.Color) {
              rgb2 = chroma(other.toString()).rgb();
          }
          else if (_.isArray(other)) {
              rgb2 = _.slice(other, 0, Math.max(other.length, 3));
          }
          else if (_.isObject(other)) {
              if (_.has(other, 'value')) {
                  rgb2 = [other.value, other.value, other.value];
              }
              else {
                  return;
              }
          }
          else {
              rgb2 = [other, other, other];
          }
  
          var rgb1 = chroma(this.toString()).rgb();
  
          for (var c = 0; c < 3; c++) {
              result[c] = tree.operate(op, rgb1[c] , rgb2[c]);
          }
  
          if (this.perceptual) {
              var normalize = function (x) {
                  return x / 255;
              };
              result = hsluv.rgbToHsluv(_.map(result, normalize));
              result[1] = result[1] / 100;
              result[2] = result[2] / 100;
          }
          else {
              result = chroma(result).hsl();
          }
  
          return new tree.Color(result, this.alpha, this.perceptual);
      }
docs: Operations have to be done in RGB per-channel, if not, channels will spill onto each other. Once we have our result, in the form of an integer triplet, we create a new Color node to hold the result.