Example #1
0
        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;
        }
Example #2
0
        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;
        }
Example #3
0
        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);
            }
        }
Example #5
0
        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);
        }
Example #7
0
 public ColourFit(ColourSet colours)
 {
     m_colours = colours;
 }