Пример #1
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;
                            }
                        }
                    }
                }
            }
Пример #2
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;
                        }
                    }
                }
            }
        }
Пример #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 (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);
                        }
                    }
                }
            }
        }
Пример #4
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");
        }
Пример #5
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);
            //        }
            //    }
            //}
        }
Пример #6
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;
                        }
                    }
                }
            }
        }