Exemplo n.º 1
0
        public AddonReader(IColorReader colorReader, List <DataFrame> frames, ILogger logger)
        {
            this.frames       = frames;
            this.logger       = logger;
            this.colorReader  = colorReader;
            this.width        = frames.Last().point.X + 1;
            this.height       = frames.Max(f => f.point.Y) + 1;
            this.squareReader = new SquareReader(this);

            var items     = JsonConvert.DeserializeObject <List <Item> >(File.ReadAllText("../json/data/items.json"));
            var creatures = JsonConvert.DeserializeObject <List <Creature> >(File.ReadAllText("../json/data/creatures.json"));

            this.BagReader       = new BagReader(squareReader, 20, items, ReadAHPrices());
            this.equipmentReader = new EquipmentReader(squareReader, 30);
            this.PlayerReader    = new PlayerReader(squareReader, creatures);
            this.LevelTracker    = new LevelTracker(PlayerReader);
        }
Exemplo n.º 2
0
            public Image Decode(Stream stream)
            {
                _stream = stream;
                _stream.Seek(8, SeekOrigin.Current);

                bool isEndChunckReached = false;

                PngChunk currentChunk = null;

                byte[] palette      = null;
                byte[] paletteAlpha = null;

                using (MemoryStream dataStream = new MemoryStream())
                {
                    while ((currentChunk = ReadChunk()) != null)
                    {
                        if (isEndChunckReached)
                        {
                            throw new ImageFormatException("Image does not end with end chunk.");
                        }

                        if (currentChunk.Type == PngChunkTypes.Header)
                        {
                            ReadHeaderChunk(currentChunk.Data);

                            ValidateHeader();
                        }
                        else if (currentChunk.Type == PngChunkTypes.Data)
                        {
                            dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length);
                        }
                        else if (currentChunk.Type == PngChunkTypes.Palette)
                        {
                            palette = currentChunk.Data;
                        }
                        else if (currentChunk.Type == PngChunkTypes.PaletteAlpha)
                        {
                            paletteAlpha = currentChunk.Data;
                        }
                        else if (currentChunk.Type == PngChunkTypes.End)
                        {
                            isEndChunckReached = true;
                        }
                    }

                    if (_header.Width > Image.MaxWidth || _header.Height > Image.MaxHeight)
                    {
                        throw new ArgumentOutOfRangeException(
                                  $"The input png '{ _header.Width }x{ _header.Height }' is bigger then the max allowed size '{ Image.MaxWidth }x{ Image.MaxHeight }'");
                    }

                    byte[] pixels = new byte[_header.Width * _header.Height * 4];

                    PngColorTypeInformation colorTypeInformation = _colorTypes[_header.ColorType];

                    if (colorTypeInformation != null)
                    {
                        IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha);

                        ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation);
                    }

                    return(new Image(_header.Width, _header.Height, pixels));
                }
            }
Exemplo n.º 3
0
            private void ReadScanlines(MemoryStream dataStream, byte[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation)
            {
                dataStream.Position = 0;

                int scanlineLength = CalculateScanlineLength(colorTypeInformation);

                int scanlineStep = CalculateScanlineStep(colorTypeInformation);

                byte[] lastScanline = new byte[scanlineLength];
                byte[] currScanline = new byte[scanlineLength];

                byte a = 0;
                byte b = 0;
                byte c = 0;

                int row = 0, filter = 0, column = -1;

                using (var compressedStream = new ZlibInflateStream(dataStream))
                {
                    int readByte = 0;
                    while ((readByte = compressedStream.ReadByte()) >= 0)
                    {
                        if (column == -1)
                        {
                            filter = readByte;

                            column++;
                        }
                        else
                        {
                            currScanline[column] = (byte)readByte;

                            if (column >= scanlineStep)
                            {
                                a = currScanline[column - scanlineStep];
                                c = lastScanline[column - scanlineStep];
                            }
                            else
                            {
                                a = 0;
                                c = 0;
                            }

                            b = lastScanline[column];

                            if (filter == 1)
                            {
                                currScanline[column] = (byte)(currScanline[column] + a);
                            }
                            else if (filter == 2)
                            {
                                currScanline[column] = (byte)(currScanline[column] + b);
                            }
                            else if (filter == 3)
                            {
                                currScanline[column] = (byte)(currScanline[column] + (byte)((a + b) / 2));
                            }
                            else if (filter == 4)
                            {
                                currScanline[column] = (byte)(currScanline[column] + PaethPredicator(a, b, c));
                            }

                            column++;

                            if (column == scanlineLength)
                            {
                                colorReader.ReadScanline(currScanline, pixels, _header);

                                column = -1;
                                row++;

                                var tmp = currScanline;
                                currScanline = lastScanline;
                                lastScanline = tmp;
                            }
                        }
                    }
                }
            }
Exemplo n.º 4
0
        private void ReadScanlines(MemoryStream dataStream, byte[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation)
        {
            // Read the zlib header : http://tools.ietf.org/html/rfc1950
            // CMF(Compression Method and flags)
            // This byte is divided into a 4 - bit compression method and a
            // 4-bit information field depending on the compression method.
            // bits 0 to 3  CM Compression method
            // bits 4 to 7  CINFO Compression info
            //
            //   0   1
            // +---+---+
            // |CMF|FLG|
            // +---+---+
            int cmf  = dataStream.ReadByte();
            int flag = dataStream.ReadByte();
            //please note that position=2


            int scanlineLength = CalculateScanlineLength(colorTypeInformation);

            int scanlineStep = CalculateScanlineStep(colorTypeInformation);

            byte[] lastScanline = new byte[scanlineLength];
            byte[] currScanline = new byte[scanlineLength];

            byte a = 0;
            byte b = 0;
            byte c = 0;

            int row = 0, filter = 0, column = -1;

            //using (InflaterInputStream compressedStream = new InflaterInputStream(dataStream))
            //{
            //    int readByte = 0;
            //    while ((readByte = compressedStream.ReadByte()) >= 0)
            //    {
            //        if (column == -1)
            //        {
            //            filter = readByte;

            //            column++;
            //        }
            //        else
            //        {
            //            currScanline[column] = (byte)readByte;

            //            if (column >= scanlineStep)
            //            {
            //                a = currScanline[column - scanlineStep];
            //                c = lastScanline[column - scanlineStep];
            //            }
            //            else
            //            {
            //                a = 0;
            //                c = 0;
            //            }

            //            b = lastScanline[column];

            //            if (filter == 1)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + a);
            //            }
            //            else if (filter == 2)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + b);
            //            }
            //            else if (filter == 3)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + (byte)Math.Floor((double)(a + b) / 2));
            //            }
            //            else if (filter == 4)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + PaethPredicator(a, b, c));
            //            }

            //            column++;

            //            if (column == scanlineLength)
            //            {
            //                colorReader.ReadScanline(currScanline, pixels, _header);

            //                column = -1;
            //                row++;

            //                Extensions.Swap(ref currScanline, ref lastScanline);
            //            }
            //        }
            //    }
            //}


            //using (Ionic.Zlib.DeflateStream compressedStream = new Ionic.Zlib.DeflateStream(dataStream, Ionic.Zlib.CompressionMode.Decompress))
            using (System.IO.Compression.DeflateStream compressedStream = new System.IO.Compression.DeflateStream(
                       dataStream,
                       System.IO.Compression.CompressionMode.Decompress, true))
            {
                int readByte = 0;
                //byte[] singleByte = new byte[1];
                //compressedStream.Read(singleByte, 0, 1);

                while ((readByte = compressedStream.ReadByte()) >= 0)
                {
                    if (column == -1)
                    {
                        filter = readByte;

                        column++;
                    }
                    else
                    {
                        currScanline[column] = (byte)readByte;

                        if (column >= scanlineStep)
                        {
                            a = currScanline[column - scanlineStep];
                            c = lastScanline[column - scanlineStep];
                        }
                        else
                        {
                            a = 0;
                            c = 0;
                        }

                        b = lastScanline[column];

                        if (filter == 1)
                        {
                            currScanline[column] = (byte)(currScanline[column] + a);
                        }
                        else if (filter == 2)
                        {
                            currScanline[column] = (byte)(currScanline[column] + b);
                        }
                        else if (filter == 3)
                        {
                            currScanline[column] = (byte)(currScanline[column] + (byte)Math.Floor((double)(a + b) / 2));
                        }
                        else if (filter == 4)
                        {
                            currScanline[column] = (byte)(currScanline[column] + PaethPredicator(a, b, c));
                        }

                        column++;

                        if (column == scanlineLength)
                        {
                            colorReader.ReadScanline(currScanline, pixels, _header);

                            column = -1;
                            row++;

                            //
                            //Extensions.Swap(ref currScanline, ref lastScanline);
                            var tmpA = currScanline;
                            var tmpB = lastScanline;

                            lastScanline = tmpA;
                            currScanline = tmpB;
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Decodes the image from the specified stream and sets
        /// the data to image.
        /// </summary>
        /// <param name="image">The image, where the data should be set to.
        /// Cannot be null (Nothing in Visual Basic).</param>
        /// <param name="stream">The stream, where the image should be
        /// decoded from. Cannot be null (Nothing in Visual Basic).</param>
        /// <exception cref="ArgumentNullException">
        ///     <para><paramref name="image"/> is null (Nothing in Visual Basic).</para>
        ///     <para>- or -</para>
        ///     <para><paramref name="stream"/> is null (Nothing in Visual Basic).</para>
        /// </exception>
        public void Decode(ExtendedImage image, Stream stream)
        {
            _image = image;

            _stream = stream;
            _stream.Seek(8, SeekOrigin.Current);

            bool isEndChunckReached = false;

            PngChunk currentChunk = null;

            byte[] palette      = null;
            byte[] paletteAlpha = null;

            using (MemoryStream dataStream = new MemoryStream())
            {
                while ((currentChunk = ReadChunk()) != null)
                {
                    if (isEndChunckReached)
                    {
                        throw new ImageFormatException("Image does not end with end chunk.");
                    }

                    if (currentChunk.Type == PngChunkTypes.Header)
                    {
                        ReadHeaderChunk(currentChunk.Data);

                        ValidateHeader();
                    }
                    else if (currentChunk.Type == PngChunkTypes.Physical)
                    {
                        ReadPhysicalChunk(currentChunk.Data);
                    }
                    else if (currentChunk.Type == PngChunkTypes.Data)
                    {
                        dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length);
                    }
                    else if (currentChunk.Type == PngChunkTypes.Palette)
                    {
                        palette = currentChunk.Data;
                    }
                    else if (currentChunk.Type == PngChunkTypes.PaletteAlpha)
                    {
                        paletteAlpha = currentChunk.Data;
                    }
                    else if (currentChunk.Type == PngChunkTypes.Text)
                    {
                        ReadTextChunk(currentChunk.Data);
                    }
                    else if (currentChunk.Type == PngChunkTypes.End)
                    {
                        isEndChunckReached = true;
                    }
                }

                byte[] pixels = new byte[_header.Width * _header.Height * 4];

                PngColorTypeInformation colorTypeInformation = _colorTypes[_header.ColorType];

                if (colorTypeInformation != null)
                {
                    IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha);

                    ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation);
                }

                image.SetPixels(_header.Width, _header.Height, pixels);
            }
        }
Exemplo n.º 6
0
        private void ReadScanlines(MemoryStream dataStream, byte[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation)
        {
            dataStream.Position = 0;

            int scanlineLength = CalculateScanlineLength(colorTypeInformation);

            int scanlineStep = CalculateScanlineStep(colorTypeInformation);

            byte[] lastScanline = new byte[scanlineLength];
            byte[] currScanline = new byte[scanlineLength];

            byte a = 0;
            byte b = 0;
            byte c = 0;

            int row = 0, filter = 0, column = -1;

            using (InflaterInputStream compressedStream = new InflaterInputStream(dataStream))
            {
                int readByte = 0;
                while ((readByte = compressedStream.ReadByte()) >= 0)
                {
                    if (column == -1)
                    {
                        filter = readByte;

                        column++;
                    }
                    else
                    {
                        currScanline[column] = (byte)readByte;

                        if (column >= scanlineStep)
                        {
                            a = currScanline[column - scanlineStep];
                            c = lastScanline[column - scanlineStep];
                        }
                        else 
                        {
                            a = 0;
                            c = 0;
                        }

                        b = lastScanline[column];

                        if (filter == 1)
                        {
                            currScanline[column] = (byte)(currScanline[column] + a);
                        }
                        else if (filter == 2)
                        {
                            currScanline[column] = (byte)(currScanline[column] + b);
                        }
                        else if (filter == 3)
                        {
                            currScanline[column] = (byte)(currScanline[column] + (byte)Math.Floor((a + b) / 2d));
                        }
                        else if (filter == 4)
                        {
                            currScanline[column] = (byte)(currScanline[column] + PaethPredicator(a, b, c)); 
                        }

                        column++;

                        if (column == scanlineLength)
                        {
                            colorReader.ReadScanline(currScanline, pixels, _header);

                            column = -1;
                            row++;

                            Extensions.Swap(ref currScanline, ref lastScanline);
                        }
                    }
                }
            }
        }
Exemplo n.º 7
0
 public DataFrameConfiguration(IColorReader colorReader)
 {
     this.colorReader = colorReader;
 }
Exemplo n.º 8
0
        private static void ParseInterlaced(byte[] data, PngFileHeader fileHeader, int bytesPerPixel, IColorReader reader, byte[] pixels)
        {
            const int passes     = 7;
            var       readOffset = 0;
            var       done       = false;
            var       r          = new Span <byte>(data);

            for (var i = 0; i < passes; i++)
            {
                int columns = Adam7.ComputeColumns(fileHeader.Width, i);
                if (columns == 0)
                {
                    continue;
                }
                int rowSize = GetScanlineLength(columns, fileHeader) + 1;

                // Read rows.
                Span <byte> prevRowData = null;
                for (int row = Adam7.FirstRow[i]; row < fileHeader.Height; row += Adam7.RowIncrement[i])
                {
                    // Early out if invalid pass.
                    if (r.Length - readOffset < rowSize)
                    {
                        done = true;
                        break;
                    }

                    var rowData = new Span <byte>(new byte[rowSize]);
                    r.Slice(readOffset, rowSize).CopyTo(rowData);
                    int filter = rowData[0];
                    rowData     = rowData.Slice(1);
                    readOffset += rowSize;

                    // Apply filter to the whole row.
                    for (var column = 0; column < rowData.Length; column++)
                    {
                        rowData[column] = ApplyFilter(rowData, prevRowData, filter, column, bytesPerPixel);
                    }

                    reader.ReadScanlineInterlaced(rowData, pixels, fileHeader, row, i);
                    prevRowData = rowData;
                }

                if (done)
                {
                    break;
                }
            }
        }
Exemplo n.º 9
0
        private static void Parse(byte[] data, PngFileHeader fileHeader, int bytesPerPixel, IColorReader reader, byte[] pixels)
        {
            // Find the scan line length.
            int scanlineLength = GetScanlineLength(fileHeader.Width, fileHeader) + 1;
            int scanLineCount  = data.Length / scanlineLength;

            // Run through all scanlines.
            var cannotParallel = new List <int>();

            ParallelWork.FastLoops(scanLineCount, (start, end) =>
            {
                int readOffset = start * scanlineLength;
                for (int i = start; i < end; i++)
                {
                    // Early out for invalid data.
                    if (data.Length - readOffset < scanlineLength)
                    {
                        break;
                    }

                    // Get the current scanline.
                    var rowData = new Span <byte>(data, readOffset + 1, scanlineLength - 1);
                    int filter  = data[readOffset];
                    readOffset += scanlineLength;

                    // Check if it has a filter.
                    // PNG filters require the previous row.
                    // We can't do those in parallel.
                    if (filter != 0)
                    {
                        lock (cannotParallel)
                        {
                            cannotParallel.Add(i);
                        }

                        continue;
                    }

                    reader.ReadScanline(rowData, pixels, fileHeader, i);
                }
            }).Wait();

            if (cannotParallel.Count == 0)
            {
                return;
            }

            PerfProfiler.ProfilerEventStart("PNG Parse Sequential", "Loading");

            // Run scanlines which couldn't be parallel processed.
            if (scanLineCount >= 2000)
            {
                Engine.Log.Trace("Loaded a big PNG with scanlines which require filtering. If you re-export it without that, it will load faster.", MessageSource.ImagePng);
            }
            cannotParallel.Sort();
            for (var i = 0; i < cannotParallel.Count; i++)
            {
                int idx = cannotParallel[i];

                int         rowStart    = idx * scanlineLength;
                Span <byte> prevRowData = idx == 0 ? null : new Span <byte>(data, (idx - 1) * scanlineLength + 1, scanlineLength - 1);
                var         rowData     = new Span <byte>(data, rowStart + 1, scanlineLength - 1);

                // Apply filter to the whole row.
                int filter = data[rowStart];
                for (var column = 0; column < rowData.Length; column++)
                {
                    rowData[column] = ApplyFilter(rowData, prevRowData, filter, column, bytesPerPixel);
                }

                reader.ReadScanline(rowData, pixels, fileHeader, idx);
            }

            PerfProfiler.ProfilerEventEnd("PNG Parse Sequential", "Loading");
        }
Exemplo n.º 10
0
        /// <summary>
        /// Decode the provided png file to a BGRA pixel array, Y flipped.
        /// </summary>
        /// <param name="pngData">The png file as bytes.</param>
        /// <param name="fileHeader">The png file's header.</param>
        /// <returns>The RGBA pixel data from the png.</returns>
        public static byte[] Decode(byte[] pngData, out PngFileHeader fileHeader)
        {
            fileHeader = new PngFileHeader();

            if (!IsPng(pngData))
            {
                Engine.Log.Warning("Tried to decode a non-png image!", MessageSource.ImagePng);
                return(null);
            }

            using var stream = new MemoryStream(pngData);
            stream.Seek(8, SeekOrigin.Current);

            var endChunkReached = false;

            byte[] palette      = null;
            byte[] paletteAlpha = null;

            using var dataStream = new MemoryStream();

            // Read chunks while there are valid chunks.
            PngChunk currentChunk;

            while ((currentChunk = new PngChunk(stream)).Valid)
            {
                if (endChunkReached)
                {
                    Engine.Log.Warning("Image did not end with an end chunk...", MessageSource.ImagePng);
                    continue;
                }

                switch (currentChunk.Type)
                {
                case PngChunkTypes.HEADER:
                {
                    Array.Reverse(currentChunk.Data, 0, 4);
                    Array.Reverse(currentChunk.Data, 4, 4);

                    fileHeader.Width  = BitConverter.ToInt32(currentChunk.Data, 0);
                    fileHeader.Height = BitConverter.ToInt32(currentChunk.Data, 4);

                    fileHeader.BitDepth          = currentChunk.Data[8];
                    fileHeader.ColorType         = currentChunk.Data[9];
                    fileHeader.FilterMethod      = currentChunk.Data[11];
                    fileHeader.InterlaceMethod   = currentChunk.Data[12];
                    fileHeader.CompressionMethod = currentChunk.Data[10];

                    // Validate header.
                    if (fileHeader.ColorType >= ColorTypes.Length || ColorTypes[fileHeader.ColorType] == null)
                    {
                        Engine.Log.Warning($"Color type '{fileHeader.ColorType}' is not supported or not valid.", MessageSource.ImagePng);
                        return(null);
                    }

                    if (!ColorTypes[fileHeader.ColorType].SupportedBitDepths.Contains(fileHeader.BitDepth))
                    {
                        Engine.Log.Warning($"Bit depth '{fileHeader.BitDepth}' is not supported or not valid for color type {fileHeader.ColorType}.", MessageSource.ImagePng);
                    }

                    if (fileHeader.FilterMethod != 0)
                    {
                        Engine.Log.Warning("The png specification only defines 0 as filter method.", MessageSource.ImagePng);
                    }
                    break;
                }

                case PngChunkTypes.DATA:
                    dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length);
                    break;

                case PngChunkTypes.PALETTE:
                    palette = currentChunk.Data;
                    break;

                case PngChunkTypes.PALETTE_ALPHA:
                    paletteAlpha = currentChunk.Data;
                    break;

                case PngChunkTypes.END:
                    endChunkReached = true;
                    break;
                }
            }

            stream.Dispose();

            // Determine color reader to use.
            PngColorTypeInformation colorTypeInformation = ColorTypes[fileHeader.ColorType];

            if (colorTypeInformation == null)
            {
                return(null);
            }
            IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha);

            // Calculate the bytes per pixel.
            var bytesPerPixel = 1;

            if (fileHeader.BitDepth >= 8)
            {
                bytesPerPixel = colorTypeInformation.ChannelsPerColor * fileHeader.BitDepth / 8;
            }

            // Decompress data.
            dataStream.Position = 0;
            PerfProfiler.ProfilerEventStart("PNG Decompression", "Loading");
            byte[] data = ZlibStreamUtility.Decompress(dataStream);
            PerfProfiler.ProfilerEventEnd("PNG Decompression", "Loading");

            // Parse into pixels.
            var pixels = new byte[fileHeader.Width * fileHeader.Height * 4];

            if (fileHeader.InterlaceMethod == 1)
            {
                ParseInterlaced(data, fileHeader, bytesPerPixel, colorReader, pixels);
            }
            else
            {
                Parse(data, fileHeader, bytesPerPixel, colorReader, pixels);
            }

            return(pixels);
        }
Exemplo n.º 11
0
        public void Decode(Image2 image, Stream stream)
        {
            Image2 currentImage = image;

            currentStream = stream;
            currentStream.Seek(8, SeekOrigin.Current);
            bool isEndChunkReached = false;

            byte[] palette      = null;
            byte[] paletteAlpha = null;
            using (MemoryStream dataStream = new MemoryStream()){
                PngChunk currentChunk;
                while ((currentChunk = ReadChunk()) != null)
                {
                    if (isEndChunkReached)
                    {
                        throw new Exception("Image does not end with end chunk.");
                    }
                    if (currentChunk.Type == PngChunkTypes.Header)
                    {
                        ReadHeaderChunk(currentChunk.Data);
                        ValidateHeader();
                    }
                    else if (currentChunk.Type == PngChunkTypes.Physical)
                    {
                        ReadPhysicalChunk(currentImage, currentChunk.Data);
                    }
                    else if (currentChunk.Type == PngChunkTypes.Data)
                    {
                        dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length);
                    }
                    else if (currentChunk.Type == PngChunkTypes.Palette)
                    {
                        palette = currentChunk.Data;
                    }
                    else if (currentChunk.Type == PngChunkTypes.PaletteAlpha)
                    {
                        paletteAlpha = currentChunk.Data;
                    }
                    else if (currentChunk.Type == PngChunkTypes.Text)
                    {
                        ReadTextChunk(currentImage, currentChunk.Data);
                    }
                    else if (currentChunk.Type == PngChunkTypes.End)
                    {
                        isEndChunkReached = true;
                    }
                }
                if (header.Width > image.MaxWidth || header.Height > image.MaxHeight)
                {
                    throw new ArgumentOutOfRangeException($"The input png '{header.Width}x{header.Height}' is bigger than the " +
                                                          $"max allowed size '{image.MaxWidth}x{image.MaxHeight}'");
                }
                Color2[] pixels = new Color2[header.Width * header.Height];
                PngColorTypeInformation colorTypeInformation = colorTypes[header.ColorType];
                if (colorTypeInformation != null)
                {
                    IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha);
                    ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation);
                }
                image.SetPixels(header.Width, header.Height, pixels);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Reads the scanlines.
        /// </summary>
        /// <param name="dataStream">The data stream.</param>
        /// <param name="pixels">The pixels.</param>
        /// <param name="colorReader">The color reader.</param>
        /// <param name="colorTypeInformation">The color type information.</param>
        /// <param name="header">The header.</param>
        private void ReadScanlines(MemoryStream dataStream, Color[] pixels, IColorReader colorReader, ColorTypeInformation colorTypeInformation, Header header)
        {
            dataStream.Seek(0, SeekOrigin.Begin);

            var ScanlineLength = CalculateScanlineLength(colorTypeInformation, header);
            var ScanlineStep   = CalculateScanlineStep(colorTypeInformation, header);

            byte[] LastScanline = new byte[ScanlineLength];
            byte[] CurrentScanline = new byte[ScanlineLength];
            int    Filter = 0, Column = -1, Row = 0;

            using (InflateStream CompressedStream = new InflateStream(dataStream))
            {
                int ReadByte;
                while ((ReadByte = CompressedStream.ReadByte()) >= 0)
                {
                    if (Column == -1)
                    {
                        Filter = ReadByte;
                        ++Column;
                    }
                    else
                    {
                        CurrentScanline[Column] = (byte)ReadByte;
                        byte a;
                        byte b;
                        byte c;
                        if (Column >= ScanlineStep)
                        {
                            a = CurrentScanline[Column - ScanlineStep];
                            c = LastScanline[Column - ScanlineStep];
                        }
                        else
                        {
                            a = 0;
                            c = 0;
                        }

                        b = LastScanline[Column];
                        switch (Filter)
                        {
                        case 1:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + a);
                            break;

                        case 2:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + b);
                            break;

                        case 3:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + (byte)((a + b) / 2));
                            break;

                        case 4:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + PaethPredicator(a, b, c));
                            break;
                        }

                        ++Column;

                        if (Column == ScanlineLength)
                        {
                            colorReader.ReadScanline(CurrentScanline, pixels, header, Row);
                            ++Row;
                            Column = -1;
                            var Holder = CurrentScanline;
                            CurrentScanline = LastScanline;
                            LastScanline    = Holder;
                        }
                    }
                }
            }
            //dataStream.Seek(0, SeekOrigin.Begin);

            //var ScanlineLength = CalculateScanlineLength(colorTypeInformation, header);
            //var ScanlineStep = CalculateScanlineStep(colorTypeInformation, header);

            //byte[] LastScanline = new byte[ScanlineLength];
            //byte[] CurrentScanline = new byte[ScanlineLength];

            //using (InflateStream CompressedStream = new InflateStream(dataStream))
            //{
            //    using (MemoryStream DecompressedStream = new MemoryStream())
            //    {
            //        CompressedStream.CopyTo(DecompressedStream);
            //        DecompressedStream.Flush();
            //        byte[] DecompressedArray = DecompressedStream.ToArray();
            //        for (int y = 0, Column = 0; y < header.Height; ++y, Column += (ScanlineLength + 1))
            //        {
            //            Array.Copy(DecompressedArray, Column + 1, CurrentScanline, 0, ScanlineLength);
            //            if (DecompressedArray[Column] < 0)
            //                break;
            //            byte[] Result = Filters[(FilterType)DecompressedArray[Column]].Decode(CurrentScanline, LastScanline, ScanlineStep);
            //            colorReader.ReadScanline(Result, pixels, header, y);
            //            Array.Copy(CurrentScanline, LastScanline, ScanlineLength);
            //        }
            //    }
            //}
        }
Exemplo n.º 13
0
        private void ReadScanlines(MemoryStream dataStream, byte[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation)
        {

            // Read the zlib header : http://tools.ietf.org/html/rfc1950
            // CMF(Compression Method and flags)
            // This byte is divided into a 4 - bit compression method and a
            // 4-bit information field depending on the compression method.
            // bits 0 to 3  CM Compression method
            // bits 4 to 7  CINFO Compression info
            //
            //   0   1
            // +---+---+
            // |CMF|FLG|
            // +---+---+
            int cmf = dataStream.ReadByte();
            int flag = dataStream.ReadByte();
            //please note that position=2


            int scanlineLength = CalculateScanlineLength(colorTypeInformation);

            int scanlineStep = CalculateScanlineStep(colorTypeInformation);

            byte[] lastScanline = new byte[scanlineLength];
            byte[] currScanline = new byte[scanlineLength];

            byte a = 0;
            byte b = 0;
            byte c = 0;

            int row = 0, filter = 0, column = -1;

            //using (InflaterInputStream compressedStream = new InflaterInputStream(dataStream)) 
            //{
            //    int readByte = 0;
            //    while ((readByte = compressedStream.ReadByte()) >= 0)
            //    {
            //        if (column == -1)
            //        {
            //            filter = readByte;

            //            column++;
            //        }
            //        else
            //        {
            //            currScanline[column] = (byte)readByte;

            //            if (column >= scanlineStep)
            //            {
            //                a = currScanline[column - scanlineStep];
            //                c = lastScanline[column - scanlineStep];
            //            }
            //            else
            //            {
            //                a = 0;
            //                c = 0;
            //            }

            //            b = lastScanline[column];

            //            if (filter == 1)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + a);
            //            }
            //            else if (filter == 2)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + b);
            //            }
            //            else if (filter == 3)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + (byte)Math.Floor((double)(a + b) / 2));
            //            }
            //            else if (filter == 4)
            //            {
            //                currScanline[column] = (byte)(currScanline[column] + PaethPredicator(a, b, c));
            //            }

            //            column++;

            //            if (column == scanlineLength)
            //            {
            //                colorReader.ReadScanline(currScanline, pixels, _header);

            //                column = -1;
            //                row++; 

            //                Extensions.Swap(ref currScanline, ref lastScanline);
            //            }
            //        }
            //    }
            //}
            using (System.IO.Compression.DeflateStream compressedStream = new System.IO.Compression.DeflateStream(
                dataStream,
                System.IO.Compression.CompressionMode.Decompress, true))
            //using (Ionic.Zlib.DeflateStream compressedStream = new Ionic.Zlib.DeflateStream(dataStream, Ionic.Zlib.CompressionMode.Decompress))
            {
                int readByte = 0;
                //byte[] singleByte = new byte[1];
                //compressedStream.Read(singleByte, 0, 1);

                while ((readByte = compressedStream.ReadByte()) >= 0)
                {
                    if (column == -1)
                    {
                        filter = readByte;

                        column++;
                    }
                    else
                    {
                        currScanline[column] = (byte)readByte;

                        if (column >= scanlineStep)
                        {
                            a = currScanline[column - scanlineStep];
                            c = lastScanline[column - scanlineStep];
                        }
                        else
                        {
                            a = 0;
                            c = 0;
                        }

                        b = lastScanline[column];

                        if (filter == 1)
                        {
                            currScanline[column] = (byte)(currScanline[column] + a);
                        }
                        else if (filter == 2)
                        {
                            currScanline[column] = (byte)(currScanline[column] + b);
                        }
                        else if (filter == 3)
                        {
                            currScanline[column] = (byte)(currScanline[column] + (byte)Math.Floor((double)(a + b) / 2));
                        }
                        else if (filter == 4)
                        {
                            currScanline[column] = (byte)(currScanline[column] + PaethPredicator(a, b, c));
                        }

                        column++;

                        if (column == scanlineLength)
                        {
                            colorReader.ReadScanline(currScanline, pixels, _header);

                            column = -1;
                            row++;

                            //
                            //Extensions.Swap(ref currScanline, ref lastScanline);
                            var tmpA = currScanline;
                            var tmpB = lastScanline;

                            lastScanline = tmpA;
                            currScanline = tmpB;
                        }
                    }
                }
            }
        }