public RangeFit(ColourSet colours, CompressionOptions flags) : base(colours) { // initialise the metric bool perceptual = ((flags & CompressionOptions.ColourMetricPerceptual) != 0); m_metric = perceptual ? new Vec3(0.2126f, 0.7152f, 0.0722f) : Vec3.One; // initialise the best error m_besterror = float.MaxValue; // cache some values var count = m_colours.Count; var values = m_colours.Points; var weights = m_colours.Weights; // get the covariance matrix Sym3x3 covariance = Sym3x3.ComputeWeightedCovariance(count, values, weights); // compute the principle component Vec3 principle = Sym3x3.ComputePrincipleComponent(covariance); // get the min and max range as the codebook endpoints Vec3 start = Vec3.Zero; Vec3 end = Vec3.Zero; if (count > 0) { float min, max; // compute the range start = end = values[0]; min = max = Vec3.Dot(values[0], principle); for (int i = 1; i < count; ++i) { float val = Vec3.Dot(values[i], principle); if (val < min) { start = values[i]; min = val; } else if (val > max) { end = values[i]; max = val; } } } // clamp the output to [0, 1] start = start.Clamp(Vec3.Zero, Vec3.One); end = end.Clamp(Vec3.Zero, Vec3.One); // clamp to the grid and save m_start = (GRID * start + HALF).Truncate() * GRIDRCP; m_end = (GRID * end + HALF).Truncate() * GRIDRCP; }