Пример #1
0
        /// <summary>
        /// Applies all PNG filters to the given scanline and returns the filtered scanline that is deemed
        /// to be most compressible, using lowest total variation as proxy for compressibility.
        /// </summary>
        /// <param name="rawScanline"></param>
        /// <param name="previousScanline"></param>
        /// <param name="bytesPerPixel"></param>
        /// <returns></returns>
        private byte[] GetOptimalFilteredScanline(byte[] rawScanline, byte[] previousScanline, int bytesPerPixel)
        {
            var candidates = new List <Tuple <byte[], int> >();

            var sub = SubFilter.Encode(rawScanline, bytesPerPixel);

            candidates.Add(new Tuple <byte[], int>(sub, CalculateTotalVariation(sub)));

            var up = UpFilter.Encode(rawScanline, previousScanline);

            candidates.Add(new Tuple <byte[], int>(up, CalculateTotalVariation(up)));

            var average = AverageFilter.Encode(rawScanline, previousScanline, bytesPerPixel);

            candidates.Add(new Tuple <byte[], int>(average, CalculateTotalVariation(average)));

            var paeth = PaethFilter.Encode(rawScanline, previousScanline, bytesPerPixel);

            candidates.Add(new Tuple <byte[], int>(paeth, CalculateTotalVariation(paeth)));

            int lowestTotalVariation      = Int32.MaxValue;
            int lowestTotalVariationIndex = 0;

            for (int i = 0; i < candidates.Count; i++)
            {
                if (candidates[i].Item2 < lowestTotalVariation)
                {
                    lowestTotalVariationIndex = i;
                    lowestTotalVariation      = candidates[i].Item2;
                }
            }

            return(candidates[lowestTotalVariationIndex].Item1);
        }
Пример #2
0
        private void DecodePixelData(byte[][] pixelData)
        {
            data = new Color[width * height];

            byte[] previousScanline = new byte[bytesPerScanline];

            for (int y = 0; y < height; y++)
            {
                var scanline = pixelData[y];

                FilterType filterType = (FilterType)scanline[0];
                byte[]     defilteredScanline;

                switch (filterType)
                {
                case FilterType.None:

                    defilteredScanline = NoneFilter.Decode(scanline);

                    break;

                case FilterType.Sub:

                    defilteredScanline = SubFilter.Decode(scanline, bytesPerPixel);

                    break;

                case FilterType.Up:

                    defilteredScanline = UpFilter.Decode(scanline, previousScanline);

                    break;

                case FilterType.Average:

                    defilteredScanline = AverageFilter.Decode(scanline, previousScanline, bytesPerPixel);

                    break;

                case FilterType.Paeth:

                    defilteredScanline = PaethFilter.Decode(scanline, previousScanline, bytesPerPixel);

                    break;

                default:
                    throw new Exception("Unknown filter type.");
                }

                previousScanline = defilteredScanline;
                ProcessDefilteredScanline(defilteredScanline, y);
            }
        }