Example #1
0
        public static ColorBlock Fit(ColorSet colors, Options options, bool isBC1)
        {
            int count = colors.Count;
            Vector3[] points = colors.Points;
            double[] weights = colors.Weights;
	
	        // compute the principle component
	        Vector3 principle = ComputePrincipleComponent(count, points, weights);

            // get the min and max range as the codebook endpoints
            Vector3 start = new Vector3();
            Vector3 end = new Vector3();
            if( count > 0 )
            {
	            double min, max;
		
	            // compute the range
	            start = end = points[0];
	            min = max = Vector3.Dot(points[0], principle);
	            for( int i = 1; i < count; ++i )
	            {
		            double val = Vector3.Dot(points[i], principle);
		            if( val < min )
		            {
			            start = points[i];
			            min = val;
		            }
		            else if( val > max )
		            {
			            end = points[i];
			            max = val;
		            }
	            }
            }
            
	        // clamp the output to [0, 1]
            start = Vector3.Clamp(start, 0.0, 1.0);
            end = Vector3.Clamp(end, 0.0, 1.0);


	        // clamp to the grid and save
            Vector3 grid = new Vector3(31.0, 63.0, 31.0);
            Vector3 gridrcp = Vector3.Reciprocal(grid);
            Vector3 half = new Vector3(0.5);

            start = Truncate(grid * start + half) * gridrcp;
            end = Truncate(grid * end + half) * gridrcp;
	
	        // create a codebook
	        Vector3[] codes = new Vector3[4];
	        codes[0] = start;
	        codes[1] = end;
            codes[2] = (2.0 / 3.0) * start + (1.0 / 3.0) * end;
            codes[3] = (1.0 / 3.0) * start + (2.0 / 3.0) * end;

	        // match each point to the closest code
	        int[] closest = new int[16];
	        double error = 0.0f;
	        for( int i = 0; i < count; ++i )
	        {
		        // find the closest code
		        double dist = double.MaxValue;
		        int idx = 0;
		        for( int j = 0; j < 4; ++j )
		        {
                    double d = (options.Metric * (points[i] - codes[j])).MagnitudeSquared;
			        if( d < dist )
			        {
				        dist = d;
				        idx = j;
			        }
		        }
		
		        // save the index
		        closest[i] = idx;
		
		        // accumulate the error
		        error += dist;
	        }
	
	        
		    // remap the indices
	        int[] indices = new int[16];
            colors.RemapIndices(closest, indices);

            return new ColorBlock(new Color(start.X, start.Y, start.Z), new Color(end.X, end.Y, end.Z), indices);
        }
Example #2
0
        public static ColorBlock Fit(ColorSet colors, Options options, bool isBC1)
        {
            int count = colors.Count;

            Vector3[] points  = colors.Points;
            double[]  weights = colors.Weights;

            // compute the principle component
            Vector3 principle = ComputePrincipleComponent(count, points, weights);

            // get the min and max range as the codebook endpoints
            Vector3 start = new Vector3();
            Vector3 end   = new Vector3();

            if (count > 0)
            {
                double min, max;

                // compute the range
                start = end = points[0];
                min   = max = Vector3.Dot(points[0], principle);
                for (int i = 1; i < count; ++i)
                {
                    double val = Vector3.Dot(points[i], principle);
                    if (val < min)
                    {
                        start = points[i];
                        min   = val;
                    }
                    else if (val > max)
                    {
                        end = points[i];
                        max = val;
                    }
                }
            }

            // clamp the output to [0, 1]
            start = Vector3.Clamp(start, 0.0, 1.0);
            end   = Vector3.Clamp(end, 0.0, 1.0);


            // clamp to the grid and save
            Vector3 grid    = new Vector3(31.0, 63.0, 31.0);
            Vector3 gridrcp = Vector3.Reciprocal(grid);
            Vector3 half    = new Vector3(0.5);

            start = Truncate(grid * start + half) * gridrcp;
            end   = Truncate(grid * end + half) * gridrcp;

            // create a codebook
            Vector3[] codes = new Vector3[4];
            codes[0] = start;
            codes[1] = end;
            codes[2] = (2.0 / 3.0) * start + (1.0 / 3.0) * end;
            codes[3] = (1.0 / 3.0) * start + (2.0 / 3.0) * end;

            // match each point to the closest code
            int[]  closest = new int[16];
            double error   = 0.0f;

            for (int i = 0; i < count; ++i)
            {
                // find the closest code
                double dist = double.MaxValue;
                int    idx  = 0;
                for (int j = 0; j < 4; ++j)
                {
                    double d = (options.Metric * (points[i] - codes[j])).MagnitudeSquared;
                    if (d < dist)
                    {
                        dist = d;
                        idx  = j;
                    }
                }

                // save the index
                closest[i] = idx;

                // accumulate the error
                error += dist;
            }


            // remap the indices
            int[] indices = new int[16];
            colors.RemapIndices(closest, indices);

            return(new ColorBlock(new Color(start.X, start.Y, start.Z), new Color(end.X, end.Y, end.Z), indices));
        }