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; }
public SingleColourFit(ColourSet colours, CompressionOptions flags) : base(colours) { // grab the single colour var values = m_colours.Points; m_colour[0] = (Byte)((255.0f * values[0].X).FloatToInt(255)); m_colour[1] = (Byte)((255.0f * values[0].Y).FloatToInt(255)); m_colour[2] = (Byte)((255.0f * values[0].Z).FloatToInt(255)); // initialise the best error m_besterror = int.MaxValue; }
public ClusterFitAlt(ColourSet colours, CompressionOptions flags) : base(colours) { // initialise the metric bool perceptual = ((flags & CompressionOptions.ColourMetricPerceptual) != 0); m_metric = perceptual ? new Vec4(0.2126f, 0.7152f, 0.0722f, 1) : Vec4.One; m_metricSqr = m_metric * m_metric; // get the covariance matrix var covariance = Sym3x3.ComputeWeightedCovariance(m_colours.Count, m_colours.Points, m_colours.Weights, m_metric.GetVec3()); // compute the principle component m_principle = Sym3x3.ComputePrincipleComponent(covariance); }
/// <summary> /// Compresses a 4x4 block of pixels. /// </summary> /// <remarks> /// The source pixels should be presented as a contiguous array of 16 rgba /// values, with each component as 1 byte each. In memory this should be: /// /// { r1, g1, b1, a1, .... , r16, g16, b16, a16 } /// /// The mask parameter enables only certain pixels within the block. The lowest /// bit enables the first pixel and so on up to the 16th bit. Bits beyond the /// 16th bit are ignored. Pixels that are not enabled are allowed to take /// arbitrary colours in the output block. An example of how this can be used /// is in the CompressImage function to disable pixels outside the bounds of /// the image when the width or height is not divisible by 4. /// /// The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression, /// however, DXT1 will be used by default if none is specified. When using DXT1 /// compression, 8 bytes of storage are required for the compressed DXT block. /// DXT3 and DXT5 compression require 16 bytes of storage per block. /// /// The flags parameter can also specify a preferred colour compressor and /// colour error metric to use when fitting the RGB components of the data. /// Possible colour compressors are: kColourClusterFit (the default), /// kColourRangeFit or kColourIterativeClusterFit. Possible colour error metrics /// are: kColourMetricPerceptual (the default) or kColourMetricUniform. If no /// flags are specified in any particular category then the default will be /// used. Unknown flags are ignored. /// /// When using kColourClusterFit, an additional flag can be specified to /// weight the colour of each pixel by its alpha value. For images that are /// rendered using alpha blending, this can significantly increase the /// perceived quality. /// </remarks> /// <param name="rgba">The rgba values of the 16 source pixels.</param> /// <param name="mask">The valid pixel mask.</param> /// <param name="flags">Compression flags.</param> public void CompressMasked(Byte[] rgba, int mask, CompressionOptions options) { System.Diagnostics.Debug.Assert(rgba != null && rgba.Length == 64, nameof(rgba)); // fix any bad flags options = options.FixFlags(); // create the minimal point set var colours = new ColourSet(rgba, mask, _Mode, options); // check the compression type and compress colour if (colours.Count == 1) { // always do a single colour fit var fit = new SingleColourFit(colours, options); fit.Compress(this); } else if ((options & CompressionOptions.ColourRangeFit) != 0 || colours.Count == 0) { // do a range fit var fit = new RangeFit(colours, options); fit.Compress(this); } else { if ((options & CompressionOptions.ColourClusterFitAlt) != 0) { var fit = new ClusterFitAlt(colours, options); fit.Compress(this); } else { // default to a cluster fit (could be iterative or not) var fit = new ClusterFit(colours, options); fit.Compress(this); } } // compress alpha separately if necessary if ((_Mode & CompressionMode.Dxt3) != 0) { this.CompressAlphaDxt3(rgba, mask); } else if ((_Mode & CompressionMode.Dxt5) != 0) { this.CompressAlphaDxt5(rgba, mask); } }
public ClusterFit(ColourSet colours, CompressionOptions flags) : base(colours) { // set the iteration count m_iterationCount = (flags & CompressionOptions.ColourIterativeClusterFit) != 0 ? MAXITERATIONS : 1; // initialise the metric bool perceptual = ((flags & CompressionOptions.ColourMetricPerceptual) != 0); m_metric = perceptual ? PERCEPTUAL : Vec4.One; // get the covariance matrix var covariance = Sym3x3.ComputeWeightedCovariance(m_colours.Count, m_colours.Points, m_colours.Weights); // compute the principle component m_principle = Sym3x3.ComputePrincipleComponent(covariance); }
public ClusterFit(ColourSet colours, CompressionOptions flags) : base(colours) { // set the iteration count m_iterationCount = (flags & CompressionOptions.ColourIterativeClusterFit) != 0 ? MAXITERATIONS : 1; // initialise the metric bool perceptual = ((flags & CompressionOptions.ColourMetricPerceptual) != 0); m_metric = perceptual ? new Vec4(0.2126f, 0.7152f, 0.0722f, 0.0f) : Vec4.One; // cache some values var count = m_colours.Count; var values = m_colours.Points; // get the covariance matrix Sym3x3 covariance = Sym3x3.ComputeWeightedCovariance(count, values, m_colours.Weights); // compute the principle component m_principle = Sym3x3.ComputePrincipleComponent(covariance); }
public ColourFit(ColourSet colours) { m_colours = colours; }