예제 #1
0
            private int CalculateScanlineStep(PngColorTypeInformation colorTypeInformation)
            {
                int scanlineStep = 1;

                if (_header.BitDepth >= 8)
                {
                    scanlineStep = (colorTypeInformation.ChannelsPerColor * _header.BitDepth) / 8;
                }

                return(scanlineStep);
            }
예제 #2
0
            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);
            }
예제 #3
0
            private void ReadScanlines(MemoryStream dataStream, byte[] pixels, ColorReader 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 (DeflaterInputStream compressedStream = new DeflaterInputStream(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++;

                                Swap(ref currScanline, ref lastScanline);
                            }
                        }
                    }
                }
            }
예제 #4
0
            /// <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 Image Decode(Stream stream)
            {
                _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 Exception("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)
                    {
                        ColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha);

                        ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation);
                    }
                    Image i = new Image(_header.Width, _header.Height);
                    int   indx = 0;
                    byte  r, g, b, a;
                    for (uint y = 0; y < i.Height; y++)
                    {
                        for (uint x = 0; x < i.Width; x++)
                        {
                            r = pixels[indx];
                            indx++;
                            g = pixels[indx];
                            indx++;
                            b = pixels[indx];
                            indx++;
                            a = pixels[indx];
                            indx++;
                            i.SetPixel(x, y, new Pixel(r, g, b, a));
                        }
                    }
                    pixels = null;
                    System.GC.Collect();
                    return(i);
                }
            }