Beispiel #1
0
        /// <summary>
        /// Decodes the raw pixel data row by row
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="pixels">The image pixel accessor.</param>
        private void DecodePixelData <TPixel>(Stream compressedStream, PixelAccessor <TPixel> pixels)
            where TPixel : struct, IPixel <TPixel>
        {
            while (this.currentRow < this.header.Height)
            {
                int bytesRead = compressedStream.Read(this.scanline, this.currentRowBytesRead, this.bytesPerScanline - this.currentRowBytesRead);
                this.currentRowBytesRead += bytesRead;
                if (this.currentRowBytesRead < this.bytesPerScanline)
                {
                    return;
                }

                this.currentRowBytesRead = 0;
                FilterType filterType = (FilterType)this.scanline[0];

                switch (filterType)
                {
                case FilterType.None:

                    NoneFilter.Decode(this.scanline);

                    break;

                case FilterType.Sub:

                    SubFilter.Decode(this.scanline, this.bytesPerScanline, this.bytesPerPixel);

                    break;

                case FilterType.Up:

                    UpFilter.Decode(this.scanline, this.previousScanline, this.bytesPerScanline);

                    break;

                case FilterType.Average:

                    AverageFilter.Decode(this.scanline, this.previousScanline, this.bytesPerScanline, this.bytesPerPixel);

                    break;

                case FilterType.Paeth:

                    PaethFilter.Decode(this.scanline, this.previousScanline, this.bytesPerScanline, this.bytesPerPixel);

                    break;

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

                this.ProcessDefilteredScanline(this.scanline, pixels);

                Swap(ref this.scanline, ref this.previousScanline);
                this.currentRow++;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Decodes the raw pixel data row by row
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="pixels">The image pixel accessor.</param>
        private void DecodePixelData <TColor, TPacked>(Stream compressedStream, PixelAccessor <TColor, TPacked> pixels)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            // TODO: ArrayPool<byte>.Shared.Rent(this.bytesPerScanline)
            byte[] previousScanline = new byte[this.bytesPerScanline];
            byte[] scanline         = new byte[this.bytesPerScanline];
            for (int y = 0; y < this.header.Height; y++)
            {
                compressedStream.Read(scanline, 0, this.bytesPerScanline);

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

                // TODO: It would be good if we can reduce the memory usage here. Each filter is creating a new row.
                switch (filterType)
                {
                case FilterType.None:

                    defilteredScanline = NoneFilter.Decode(scanline);

                    break;

                case FilterType.Sub:

                    defilteredScanline = SubFilter.Decode(scanline, this.bytesPerPixel);

                    break;

                case FilterType.Up:

                    defilteredScanline = UpFilter.Decode(scanline, previousScanline);

                    break;

                case FilterType.Average:

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

                    break;

                case FilterType.Paeth:

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

                    break;

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

                previousScanline = defilteredScanline;
                this.ProcessDefilteredScanline(defilteredScanline, y, pixels);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Decodes the raw pixel data row by row
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="pixelData">The pixel data.</param>
        /// <param name="pixels">The image pixels.</param>
        private void DecodePixelData <TColor, TPacked>(byte[] pixelData, TColor[] pixels)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            byte[] previousScanline = new byte[this.bytesPerScanline];

            for (int y = 0; y < this.header.Height; y++)
            {
                byte[] scanline = new byte[this.bytesPerScanline];
                Array.Copy(pixelData, y * this.bytesPerScanline, scanline, 0, this.bytesPerScanline);
                FilterType filterType = (FilterType)scanline[0];
                byte[]     defilteredScanline;

                switch (filterType)
                {
                case FilterType.None:

                    defilteredScanline = NoneFilter.Decode(scanline);

                    break;

                case FilterType.Sub:

                    defilteredScanline = SubFilter.Decode(scanline, this.bytesPerPixel);

                    break;

                case FilterType.Up:

                    defilteredScanline = UpFilter.Decode(scanline, previousScanline);

                    break;

                case FilterType.Average:

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

                    break;

                case FilterType.Paeth:

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

                    break;

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

                previousScanline = defilteredScanline;
                this.ProcessDefilteredScanline <TColor, TPacked>(defilteredScanline, y, pixels);
            }
        }
        /// <summary>
        /// Decodes the raw interlaced pixel data row by row
        /// <see href="https://github.com/juehv/DentalImageViewer/blob/8a1a4424b15d6cc453b5de3f273daf3ff5e3a90d/DentalImageViewer/lib/jiu-0.14.3/net/sourceforge/jiu/codecs/PNGCodec.java"/>
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="pixels">The image pixel accessor.</param>
        private void DecodeInterlacedPixelData <TColor>(Stream compressedStream, PixelAccessor <TColor> pixels)
            where TColor : struct, IPixel <TColor>
        {
            byte[] previousScanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            byte[] scanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            try
            {
                for (int pass = 0; pass < 7; pass++)
                {
                    // Zero out the scanlines, because the bytes that are rented from the arraypool may not be zero.
                    Array.Clear(scanline, 0, this.bytesPerScanline);
                    Array.Clear(previousScanline, 0, this.bytesPerScanline);

                    int y          = Adam7FirstRow[pass];
                    int numColumns = this.ComputeColumnsAdam7(pass);

                    if (numColumns == 0)
                    {
                        // This pass contains no data; skip to next pass
                        continue;
                    }

                    int bytesPerInterlaceScanline = this.CalculateScanlineLength(numColumns) + 1;

                    while (y < this.header.Height)
                    {
                        compressedStream.Read(scanline, 0, bytesPerInterlaceScanline);

                        FilterType filterType = (FilterType)scanline[0];

                        switch (filterType)
                        {
                        case FilterType.None:

                            NoneFilter.Decode(scanline);

                            break;

                        case FilterType.Sub:

                            SubFilter.Decode(scanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                            break;

                        case FilterType.Up:

                            UpFilter.Decode(scanline, previousScanline, bytesPerInterlaceScanline);

                            break;

                        case FilterType.Average:

                            AverageFilter.Decode(scanline, previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                            break;

                        case FilterType.Paeth:

                            PaethFilter.Decode(scanline, previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);

                            break;

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

                        this.ProcessInterlacedDefilteredScanline(scanline, y, pixels, Adam7FirstColumn[pass], Adam7ColumnIncrement[pass]);

                        Swap(ref scanline, ref previousScanline);

                        y += Adam7RowIncrement[pass];
                    }
                }
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(previousScanline);

                ArrayPool <byte> .Shared.Return(scanline);
            }
        }
        /// <summary>
        /// Decodes the raw pixel data row by row
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="pixels">The image pixel accessor.</param>
        private void DecodePixelData <TColor>(Stream compressedStream, PixelAccessor <TColor> pixels)
            where TColor : struct, IPixel <TColor>
        {
            byte[] previousScanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            byte[] scanline = ArrayPool <byte> .Shared.Rent(this.bytesPerScanline);

            // Zero out the scanlines, because the bytes that are rented from the arraypool may not be zero.
            Array.Clear(scanline, 0, this.bytesPerScanline);
            Array.Clear(previousScanline, 0, this.bytesPerScanline);

            try
            {
                for (int y = 0; y < this.header.Height; y++)
                {
                    compressedStream.Read(scanline, 0, this.bytesPerScanline);

                    FilterType filterType = (FilterType)scanline[0];

                    switch (filterType)
                    {
                    case FilterType.None:

                        NoneFilter.Decode(scanline);

                        break;

                    case FilterType.Sub:

                        SubFilter.Decode(scanline, this.bytesPerScanline, this.bytesPerPixel);

                        break;

                    case FilterType.Up:

                        UpFilter.Decode(scanline, previousScanline, this.bytesPerScanline);

                        break;

                    case FilterType.Average:

                        AverageFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel);

                        break;

                    case FilterType.Paeth:

                        PaethFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel);

                        break;

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

                    this.ProcessDefilteredScanline(scanline, y, pixels);

                    Swap(ref scanline, ref previousScanline);
                }
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(previousScanline);

                ArrayPool <byte> .Shared.Return(scanline);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Decodes the raw interlaced pixel data row by row
        /// <see href="https://github.com/juehv/DentalImageViewer/blob/8a1a4424b15d6cc453b5de3f273daf3ff5e3a90d/DentalImageViewer/lib/jiu-0.14.3/net/sourceforge/jiu/codecs/PNGCodec.java"/>
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="compressedStream">The compressed pixel data stream.</param>
        /// <param name="image">The current image.</param>
        private void DecodeInterlacedPixelData <TPixel>(Stream compressedStream, Image <TPixel> image)
            where TPixel : struct, IPixel <TPixel>
        {
            while (true)
            {
                int numColumns = this.ComputeColumnsAdam7(this.pass);

                if (numColumns == 0)
                {
                    this.pass++;

                    // This pass contains no data; skip to next pass
                    continue;
                }

                int bytesPerInterlaceScanline = this.CalculateScanlineLength(numColumns) + 1;

                while (this.currentRow < this.header.Height)
                {
                    int bytesRead = compressedStream.Read(this.scanline.Array, this.currentRowBytesRead, bytesPerInterlaceScanline - this.currentRowBytesRead);
                    this.currentRowBytesRead += bytesRead;
                    if (this.currentRowBytesRead < bytesPerInterlaceScanline)
                    {
                        return;
                    }

                    this.currentRowBytesRead = 0;

                    Span <byte> scanSpan   = this.scanline.Slice(0, bytesPerInterlaceScanline);
                    Span <byte> prevSpan   = this.previousScanline.Slice(0, bytesPerInterlaceScanline);
                    var         filterType = (FilterType)scanSpan[0];

                    switch (filterType)
                    {
                    case FilterType.None:
                        break;

                    case FilterType.Sub:

                        SubFilter.Decode(scanSpan, this.bytesPerPixel);
                        break;

                    case FilterType.Up:

                        UpFilter.Decode(scanSpan, prevSpan);
                        break;

                    case FilterType.Average:

                        AverageFilter.Decode(scanSpan, prevSpan, this.bytesPerPixel);
                        break;

                    case FilterType.Paeth:

                        PaethFilter.Decode(scanSpan, prevSpan, this.bytesPerPixel);
                        break;

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

                    Span <TPixel> rowSpan = image.GetRowSpan(this.currentRow);
                    this.ProcessInterlacedDefilteredScanline(this.scanline.Array, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);

                    Swap(ref this.scanline, ref this.previousScanline);

                    this.currentRow += Adam7RowIncrement[this.pass];
                }

                this.pass++;
                this.previousScanline.Clear();

                if (this.pass < 7)
                {
                    this.currentRow = Adam7FirstRow[this.pass];
                }
                else
                {
                    this.pass = 0;
                    break;
                }
            }
        }