Options for the usage of the TrigradCompressor.
Пример #1
0
        private static double errorPolygon(Sample s, PixelMap original, TrigradOptions options)
        {
            if(options.ResampleColors)
            foreach (var sample in s.Samples)
            {
                sample.Color = original[sample.Point];
            }

            double error = 0d;
            foreach (var t in s.Triangles)
            {
                t.CenterColor = original[t.CenterPoint];

                options.Renderer.Fill(t,tempMap);

                foreach (var drawPoint in t.Points)
                {
                    Pixel a = original[drawPoint.Point];
                    Pixel b = tempMap[drawPoint.Point];

                    Pixel diff = a - b;

                    error += diff.R;
                    error += diff.G;
                    error += diff.B;
                }
            }
            return error;
        }
Пример #2
0
        private static void drawMesh(List<SampleTri> mesh, PixelMap output, TrigradOptions options)
        {
            int i = 0;
            int count = mesh.Count;
            foreach (var triangle in mesh)
            {
                options.Renderer.Fill(triangle,output);

                if (i % 50 == 0 && OnUpdate != null)
                    OnUpdate((double)i / count);

                i++;
            }
        }
Пример #3
0
        /// <summary> Decompresses a trigrad compressed bitmap. </summary>
        /// <param name="compressionData"> The TrigradCompressed data.</param>
        /// <param name="original"> The original image to determine the most effect fill mode.</param>
        /// <param name="options"> Options dictating the decompression.</param>
        public static TrigradDecompressed DecompressBitmap(TrigradCompressed compressionData, TrigradOptions options)
        {
            TrigradDecompressed decompressed = new TrigradDecompressed(compressionData.Width, compressionData.Height);

            for (int x = 0; x < compressionData.Width; x++)
                for (int y = 0; y < compressionData.Height; y++)
                    decompressed.Output[x, y] = new Pixel(Color.HotPink);

            drawMesh(compressionData.Mesh, decompressed.Output, options);

            fillGaps(decompressed.Output);

            return decompressed;
        }
        /// <summary> Compresses a bitmap using TrigradCompression. </summary>
        /// <param name="bitmap"> The input bitmap.</param>
        /// <param name="options"> TrigradOptions specifying how the image will be compressed.</param>
        public static TrigradCompressed CompressBitmap(Bitmap bitmap, TrigradOptions options)
        {
            TrigradCompressed compressed = new TrigradCompressed { Height = bitmap.Height, Width = bitmap.Width };
            List<Point> samplePoints = new List<Point>();

            samplePoints.Add(new Point(0, 0));
            samplePoints.Add(new Point(bitmap.Width - 1, 0));
            samplePoints.Add(new Point(0, bitmap.Height - 1));
            samplePoints.Add(new Point(bitmap.Width - 1, bitmap.Height - 1));

            double baseChance = 1d / ((double)(bitmap.Width * bitmap.Height) / options.SampleCount / 8);

            for (int x = 0; x < bitmap.Width; x++)
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    double chance = ((options.FrequencyTable != null) ? options.FrequencyTable.Table[x, y] : 1d) * baseChance;

                    if (options.Random.NextDouble() < chance)
                    {
                        samplePoints.Add(new Point(x, y));
                    }
                }
            }

            foreach (var sample in samplePoints)
            {
                List<Color> averageColors = new List<Color>();

                for (int x = sample.X - options.SampleRadius; x < sample.X + options.SampleRadius + 1; x++)
                {
                    for (int y = sample.Y - options.SampleRadius; y < sample.Y + options.SampleRadius + 1; y++)
                    {
                        if (y >= 0 && y < bitmap.Height && x >= 0 && x < bitmap.Width)
                        {
                            averageColors.Add(bitmap.GetPixel(x, y));
                        }
                    }
                }

                byte R = (byte)averageColors.Average(c => c.R);
                byte G = (byte)averageColors.Average(c => c.G);
                byte B = (byte)averageColors.Average(c => c.B);
                compressed.SampleTable[sample] = Color.FromArgb(R, G, B);
            }

            return compressed;
        }
Пример #5
0
        public static void OptimiseMesh(TrigradCompressed compressionData, PixelMap original, TrigradOptions options)
        {
            var mesh = compressionData.Mesh;
            GPUT.CalculateMesh(mesh);

            var samples = mesh.SelectMany(t => t.Samples).Distinct().ToList();

            for (int i = 0; i < options.Iterations; i++)
            {
                minimiseMesh(samples, options, original);

                Console.WriteLine("{0}/{1}", i, options.Iterations);
            }

            compressionData.Mesh = mesh;
        }
Пример #6
0
        /// <summary> Compresses a bitmap using TrigradCompression. </summary>
        /// <param name="pixelmap"> The input bitmap.</param>
        /// <param name="options"> TrigradOptions specifying how the image will be compressed.</param>
        public static TrigradCompressed CompressBitmap(PixelMap pixelmap, TrigradOptions options)
        {
            TrigradCompressed compressed = new TrigradCompressed { Height = pixelmap.Height, Width = pixelmap.Width };

            double baseChance = options.SampleCount / (options.FrequencyTable.Sum);

            int i = 0;
            int count = pixelmap.Width * pixelmap.Height;
            for (int x = 0; x < pixelmap.Width; x++)
            {
                for (int y = 0; y < pixelmap.Height; y++)
                {
                    if ((x == 0 && y == 0) ||
                        (x == pixelmap.Width - 1 && y == 0) ||
                        (x == 0 && y == pixelmap.Height - 1) ||
                        (x == pixelmap.Width - 1 && y == pixelmap.Height - 1))
                    {
                        compressed.SampleTable[new Point(x, y)] = pixelmap[new Point(x, y)];
                        continue;
                    }

                    double chance = ((options.FrequencyTable != null)
                        ? options.FrequencyTable.Table[x, y]
                        : 1d) * baseChance;

                    lock(options.Random)
                    if (options.Random.NextDouble() < chance)
                    {
                        lock (compressed.SampleTable)
                            compressed.SampleTable[new Point(x, y)] = pixelmap[new Point(x, y)];
                    }

                    if (i % 50 == 0 && OnUpdate != null)
                        OnUpdate((double)i / count);

                    i++;
                }
            }

            return compressed;
        }
Пример #7
0
        private static void minimiseSample(Sample s, int resamples, PixelMap original, TrigradOptions options)
        {
            if (s.Point.X == 0 || s.Point.Y == 0)
                return;

            if (s.Point.X == original.Width - 1 || s.Point.Y == original.Height - 1)
                return;

            var curPoints = s.Points;

            double minError = errorPolygon(s, original, options);
            Point bestPoint = s.Point;

            if (polygonConvex(s))
                return;

            int count = curPoints.Count;
            int skip = count / resamples;
            if (skip == 0)
                skip = 1;

            foreach (var drawPoint in curPoints.Where((x, i) => i % skip == 0))
            {
                s.Point = drawPoint.Point;

                TriangleRasterization.CalculateMesh(s.Triangles);

                double error = errorPolygon(s, original, options);
                if (error < minError)
                {
                    bestPoint = drawPoint.Point;
                    minError = error;
                }
            }

            s.Point = bestPoint;
            TriangleRasterization.CalculateMesh(s.Triangles);
        }
Пример #8
0
        static void minimiseMesh(List<Sample> samples, TrigradOptions options, PixelMap original)
        {
            tempMap = new PixelMap(original.Width,original.Height);

            int o = 0;
            int count = samples.Count;
            foreach (var sample in samples)
            {
                minimiseSample(sample, options.Resamples, original, options);

                o++;

                if (o%1000 == 0)
                    Console.WriteLine("{0}/{1}", o, samples.Count);

                if (o%100 == 0 && OnUpdate != null)
                    OnUpdate((double)o/count);
            }
        }
Пример #9
0
        static void Main(string[] args)
        {
            Stopwatch s = new Stopwatch();
            s.Start();
            Console.WriteLine("Trigrad");
            string input = "tests\\input\\Tulips.jpg";

            PixelMap inputBitmap = PixelMap.SlowLoad(new Bitmap(input));
            FrequencyTable table = new FrequencyTable(inputBitmap,1);

            var options = new TrigradOptions
            {
                SampleCount = 40000,
                FrequencyTable = table,
                Resamples = 4,
                Iterations =0,
                Random = new Random(0),
                ResampleColors = true,
                Renderer = new ShapeFill(3)
            };

            var results = TrigradCompressor.CompressBitmap(inputBitmap, options);

            results.DebugVisualisation().GetBitmap().Save("tests\\points.png");

            results.Mesh = MeshBuilder.BuildMesh(results.SampleTable);
            results.MeshOutput(inputBitmap).GetBitmap().Save("tests\\mesh_a.png");

            TrigradOptimiser.OptimiseMesh(results, inputBitmap, options);

            GPUT.CalculateMesh(results.Mesh);

            //results.Save(new FileStream("tests\\out.tri", FileMode.Create));

            results.MeshOutput(inputBitmap).GetBitmap().Save("tests\\mesh_b.png");

            Console.WriteLine(results.SampleTable.Count);

            //var loaded = new TrigradCompressed(new FileStream("tests\\out.tri", FileMode.Open));

            //results.Mesh = results.Mesh.OrderBy(t => t.CenterColor.Lightness).ToList();
            results.Mesh.Shuffle(options.Random);

            var returned = TrigradDecompressor.DecompressBitmap(results, options);

            returned.Output.GetBitmap().Save("tests\\output.png");
            returned.DebugOutput.GetBitmap().Save("tests\\debug_output.png");

            int error = errorBitmap(inputBitmap, returned.Output);
            double avgError = Math.Round((double)error / (inputBitmap.Width * inputBitmap.Height * 3), 2);

            Console.WriteLine("{0} error", avgError);
            Console.WriteLine("{0} s", Math.Round(s.ElapsedMilliseconds / 1000d, 2));

            saveBackup(avgError, Path.GetFileNameWithoutExtension(input), options);

            Console.Beep();
            Console.ReadKey();
        }
Пример #10
0
        static void saveBackup(double error, string file, TrigradOptions options)
        {
            Random r = new Random();

            var path = Path.Combine(backup, string.Format("{0} Test #{1}, {2} err, {3} samples, {4} resamples, {5} iterations", file, r.Next(), error, options.SampleCount, options.Resamples, options.Iterations));
            Directory.CreateDirectory(path);

            File.Copy("tests\\points.png", Path.Combine(path, "points.png"));
            File.Copy("tests\\output.png", Path.Combine(path, "output.png"));
            //File.Copy("tests\\debug_output.png", Path.Combine(path, "debug_output.png"));
            File.Copy("tests\\mesh_a.png", Path.Combine(path, "mesh_a.png"));
            File.Copy("tests\\mesh_b.png", Path.Combine(path, "mesh_b.png"));
            File.Copy("tests\\error.png", Path.Combine(path, "error.png"));
        }