/// <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="image">The image to decode to.</param> private void DecodePixelData <TPixel>(Stream compressedStream, ImageFrame <TPixel> image) where TPixel : struct, IPixel <TPixel> { while (this.currentRow < this.header.Height) { int bytesRead = compressedStream.Read(this.scanline.Array, this.currentRowBytesRead, this.bytesPerScanline - this.currentRowBytesRead); this.currentRowBytesRead += bytesRead; if (this.currentRowBytesRead < this.bytesPerScanline) { return; } this.currentRowBytesRead = 0; var filterType = (FilterType)this.scanline[0]; switch (filterType) { case FilterType.None: break; case FilterType.Sub: SubFilter.Decode(this.scanline, this.bytesPerPixel); break; case FilterType.Up: UpFilter.Decode(this.scanline, this.previousScanline); break; case FilterType.Average: AverageFilter.Decode(this.scanline, this.previousScanline, this.bytesPerPixel); break; case FilterType.Paeth: PaethFilter.Decode(this.scanline, this.previousScanline, this.bytesPerPixel); break; default: throw new ImageFormatException("Unknown filter type."); } this.ProcessDefilteredScanline(this.scanline.Array, image); Swap(ref this.scanline, ref this.previousScanline); this.currentRow++; } }
private void DecodePixelData(byte[][] pixelData) { // data = new Color[_width * _height]; _colors = new Color[width * height]; pixels = new int[width * height]; var previousScanline = new byte[bytesPerScanline]; for (var y = 0; y < height; ++y) { var scanline = pixelData[y]; byte[] defilteredScanline; switch (scanline[0]) { case 0: defilteredScanline = NoneFilter.Decode(scanline); break; case 1: defilteredScanline = SubFilter.Decode(scanline, bytesPerPixel); break; case 2: defilteredScanline = UpFilter.Decode(scanline, previousScanline); break; case 3: defilteredScanline = AverageFilter.Decode(scanline, previousScanline, bytesPerPixel); break; case 4: defilteredScanline = PaethFilter.Decode(scanline, previousScanline, bytesPerPixel); break; default: throw new Exception("Unknown filter type."); } previousScanline = defilteredScanline; ProcessDefilteredScanline(defilteredScanline, y); } }
/// <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, ImageFrame <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.GetPixelRowSpan(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; } } }