Пример #1
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;
                }
            }
        }
Пример #2
0
        private static byte[] ParseInterlaced(byte[] pureData, PngFileHeader fileHeader, int bytesPerPixel, int channelsPerColor, ColorReader reader)
        {
            PerfProfiler.ProfilerEventStart("PNG Parse Interlaced", "Loading");

            // Combine interlaced pixels into one image here.
            var width       = (int)fileHeader.Size.X;
            var height      = (int)fileHeader.Size.Y;
            var combination = new byte[width * height * channelsPerColor];
            var pixels      = new byte[width * height * 4];

            const int passes     = 7;
            var       readOffset = 0;
            var       done       = false;
            var       data       = new Span <byte>(pureData);

            for (var i = 0; i < passes; i++)
            {
                int columns = Adam7.ComputeColumns(width, i);
                if (columns == 0)
                {
                    continue;
                }
                int scanlineLength = GetScanlineLengthInterlaced(columns, fileHeader, channelsPerColor) + 1;
                int length         = scanlineLength - 1;

                int pixelsInLine = Adam7.ComputeBlockWidth(width, i);

                // Read scanlines in this pass.
                var previousScanline = Span <byte> .Empty;
                for (int row = Adam7.FirstRow[i]; row < height; row += Adam7.RowIncrement[i])
                {
                    // Early out if invalid pass.
                    if (data.Length - readOffset < scanlineLength)
                    {
                        done = true;
                        break;
                    }

                    Span <byte> scanLine = data.Slice(readOffset + 1, length);
                    int         filter   = data[readOffset];
                    readOffset += scanlineLength;
                    ApplyFilter(scanLine, previousScanline, filter, bytesPerPixel);

                    // Dump the row into the combined image.
                    Span <byte> convertedLine = ConvertBitArray(scanLine, fileHeader);
                    for (var pixel = 0; pixel < pixelsInLine; pixel++)
                    {
                        int offset    = row * bytesPerPixel * width + (Adam7.FirstColumn[i] + pixel * Adam7.ColumnIncrement[i]) * bytesPerPixel;
                        int offsetSrc = pixel * bytesPerPixel;
                        for (var p = 0; p < bytesPerPixel; p++)
                        {
                            combination[offset + p] = convertedLine[offsetSrc + p];
                        }
                    }

                    previousScanline = scanLine;
                }

                if (done)
                {
                    break;
                }
            }

            // Read the combined image.
            int stride        = width * bytesPerPixel;
            int scanlineCount = combination.Length / stride;

            for (var i = 0; i < scanlineCount; i++)
            {
                Span <byte> row = new Span <byte>(combination).Slice(stride * i, stride);
                reader(width, row, pixels, i);
            }

            PerfProfiler.ProfilerEventEnd("PNG Parse Interlaced", "Loading");
            return(pixels);
        }