/// <summary> /// Calculates the length of the scanline. /// </summary> /// <param name="colorTypeInformation">The color type information.</param> /// <param name="header">The header.</param> /// <returns>The scanline length</returns> private static int CalculateScanlineLength(ColorTypeInformation colorTypeInformation, Header header) { int ScanlineLength = header.Width * header.BitDepth * colorTypeInformation.ScanlineFactor; int Amount = ScanlineLength % 8; if (Amount != 0) { ScanlineLength += 8 - Amount; } return(ScanlineLength / 8); }
/// <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); // } // } //} }
/// <summary> /// Calculates the scanline step. /// </summary> /// <param name="colorTypeInformation">The color type information.</param> /// <param name="header">The header.</param> /// <returns>The scanline step</returns> private static int CalculateScanlineStep(ColorTypeInformation colorTypeInformation, Header header) { return(header.BitDepth >= 8 ? (colorTypeInformation.ScanlineFactor * header.BitDepth) / 8 : 1); }