private int CalculateScanlineStep(PngColorTypeInformation colorTypeInformation) { int scanlineStep = 1; if (_header.BitDepth >= 8) { scanlineStep = (colorTypeInformation.ChannelsPerColor * _header.BitDepth) / 8; } return(scanlineStep); }
private int CalculateScanlineLength(PngColorTypeInformation colorTypeInformation) { int scanlineLength = (_header.Width * _header.BitDepth * colorTypeInformation.ChannelsPerColor); int amount = scanlineLength % 8; if (amount != 0) { scanlineLength += 8 - amount; } return(scanlineLength / 8); }
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; } } } } }
/// <summary> /// Decodes the image from the specified stream and sets /// the data to image. /// </summary> /// <param name="image">The image, where the data should be set to. /// Cannot be null (Nothing in Visual Basic).</param> /// <param name="stream">The stream, where the image should be /// decoded from. Cannot be null (Nothing in Visual Basic).</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="image"/> is null (Nothing in Visual Basic).</para> /// <para>- or -</para> /// <para><paramref name="stream"/> is null (Nothing in Visual Basic).</para> /// </exception> public void Decode(ExtendedImage image, Stream stream) { _image = image; _stream = stream; _stream.Seek(8, SeekOrigin.Current); bool isEndChunckReached = false; PngChunk currentChunk = null; byte[] palette = null; byte[] paletteAlpha = null; using (MemoryStream dataStream = new MemoryStream()) { while ((currentChunk = ReadChunk()) != null) { if (isEndChunckReached) { throw new ImageFormatException("Image does not end with end chunk."); } if (currentChunk.Type == PngChunkTypes.Header) { ReadHeaderChunk(currentChunk.Data); ValidateHeader(); } else if (currentChunk.Type == PngChunkTypes.Physical) { ReadPhysicalChunk(currentChunk.Data); } else if (currentChunk.Type == PngChunkTypes.Data) { dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length); } else if (currentChunk.Type == PngChunkTypes.Palette) { palette = currentChunk.Data; } else if (currentChunk.Type == PngChunkTypes.PaletteAlpha) { paletteAlpha = currentChunk.Data; } else if (currentChunk.Type == PngChunkTypes.Text) { ReadTextChunk(currentChunk.Data); } else if (currentChunk.Type == PngChunkTypes.End) { isEndChunckReached = true; } } byte[] pixels = new byte[_header.Width * _header.Height * 4]; PngColorTypeInformation colorTypeInformation = _colorTypes[_header.ColorType]; if (colorTypeInformation != null) { IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha); ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation); } image.SetPixels(_header.Width, _header.Height, pixels); } }
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); } } } } }
private int CalculateScanlineStep(PngColorTypeInformation colorTypeInformation) { int scanlineStep = 1; if (_header.BitDepth >= 8) { scanlineStep = (colorTypeInformation.ChannelsPerColor * _header.BitDepth) / 8; } return scanlineStep; }
private int CalculateScanlineLength(PngColorTypeInformation colorTypeInformation) { int scanlineLength = (_header.Width * _header.BitDepth * colorTypeInformation.ChannelsPerColor); int amount = scanlineLength % 8; if (amount != 0) { scanlineLength += 8 - amount; } return scanlineLength / 8; }
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; } } } } }