Ejemplo n.º 1
0
        /// <summary>
        /// Decodes per-row delta-encoded and then Deflate-compressed data from a source stream and writes the decoded
        /// data to a target stream.
        /// </summary>
        /// <remarks><paramref name="source"/> must already be at the correct position.</remarks>
        /// <param name="source">The stream from which to copy the data.</param>
        /// <param name="dest">The stream to which to copy the data.</param>
        /// <param name="length">
        /// The number of bytes to copy from the source stream, or <c>null</c> to copy all data until the source stream
        /// ends.
        /// </param>
        /// <param name="depth">The depth of the image in bits per pixel color component.</param>
        /// <param name="imageWidth">The width of the image in pixels.</param>
        /// <param name="cancelToken">
        /// A cancellation token which allows copying to be cancelled before it completes.
        /// </param>
        public static void DecodeZipPredicted(Stream source, Stream dest, long?length, int depth, int imageWidth,
                                              CancellationToken cancelToken = default(CancellationToken))
        {
            if (depth == 1 || depth == 8)
            {
                // no prediction here
                DecodeZip(source, dest, length, cancelToken);
                return;
            }

            Stream actualSource = length.HasValue
                ? new PartialStream(source, source.Position, length.Value)
                : source;

            // skip zlib header
            source.ReadBytes(2);

            var buf = new byte[imageWidth * (depth / 8)];

            using (var inflater = new DeflateStream(actualSource, CompressionMode.Decompress, leaveOpen: true))
            {
                for (;;)
                {
                    try
                    {
                        inflater.ReadBytes(buf);
                    }
                    catch (EndOfStreamException)
                    {
                        break;
                    }

                    if (depth == 16)
                    {
                        DeltaEncoding.DeltaDecodeBigEndian16(buf);
                        dest.Write(buf, 0, buf.Length);
                    }
                    else if (depth == 32)
                    {
                        DeltaEncoding.DeltaDecodeBigEndian32(buf);
                        dest.Write(buf, 0, buf.Length);
                    }

                    cancelToken.ThrowIfCancellationRequested();
                }
            }
        }
Ejemplo n.º 2
0
        public byte[] GetTrueBytes(FileEntry entry)
        {
            if (!entry.IsCompressed)
            {
                return(GetRawBytes(entry));
            }
            if (entry.OriginalData != null)
            {
                using (var ms = new MemoryStream(entry.OriginalData))
                    using (var ds = new DeflateStream(ms, CompressionMode.Decompress))
                    {
                        return(ds.ReadBytes(entry.Length));
                    }
            }

            using (Stream s = GetStream(entry))
                using (DeflateStream ds = new DeflateStream(s, CompressionMode.Decompress))
                {
                    return(ds.ReadBytes(entry.Length));
                }
        }
Ejemplo n.º 3
0
        public Png(Stream s)
        {
            if (!Verify(s))
            {
                throw new InvalidDataException("PNG Signature is bogus");
            }

            s.Position += 8;
            var headerParsed = false;

            var data = new List <byte>();

            for (;;)
            {
                var length  = IPAddress.NetworkToHostOrder(s.ReadInt32());
                var type    = Encoding.UTF8.GetString(s.ReadBytes(4));
                var content = s.ReadBytes(length);
                /*var crc = */ s.ReadInt32();

                if (!headerParsed && type != "IHDR")
                {
                    throw new InvalidDataException("Invalid PNG file - header does not appear first.");
                }

                using (var ms = new MemoryStream(content))
                {
                    switch (type)
                    {
                    case "IHDR":
                    {
                        if (headerParsed)
                        {
                            throw new InvalidDataException("Invalid PNG file - duplicate header.");
                        }
                        Width  = IPAddress.NetworkToHostOrder(ms.ReadInt32());
                        Height = IPAddress.NetworkToHostOrder(ms.ReadInt32());
                        Data   = new byte[Width * Height];

                        var bitDepth  = ms.ReadUInt8();
                        var colorType = (PngColorType)ms.ReadByte();
                        PixelFormat = MakePixelFormat(bitDepth, colorType);

                        var compression = ms.ReadByte();
                        /*var filter = */ ms.ReadByte();
                        var interlace = ms.ReadByte();

                        if (compression != 0)
                        {
                            throw new InvalidDataException("Compression method not supported");
                        }

                        if (interlace != 0)
                        {
                            throw new InvalidDataException("Interlacing not supported");
                        }

                        headerParsed = true;

                        break;
                    }

                    case "PLTE":
                    {
                        Palette = new Color[256];
                        for (var i = 0; i < length / 3; i++)
                        {
                            var r = ms.ReadByte(); var g = ms.ReadByte(); var b = ms.ReadByte();
                            Palette[i] = Color.FromArgb(r, g, b);
                        }

                        break;
                    }

                    case "tRNS":
                    {
                        if (Palette == null)
                        {
                            throw new InvalidDataException("Non-Palette indexed PNG are not supported.");
                        }

                        for (var i = 0; i < length; i++)
                        {
                            Palette[i] = Color.FromArgb(ms.ReadByte(), Palette[i]);
                        }

                        break;
                    }

                    case "IDAT":
                    {
                        data.AddRange(content);

                        break;
                    }

                    case "tEXt":
                    {
                        var key = ms.ReadASCIIZ();
                        EmbeddedData.Add(key, ms.ReadASCII(length - key.Length - 1));

                        break;
                    }

                    case "IEND":
                    {
                        using (var ns = new MemoryStream(data.ToArray()))
                        {
                            // 'zlib' flags bytes; confuses the DeflateStream.
                            /*var flags = (byte)*/ ns.ReadByte();
                            /*var moreFlags = (byte)*/ ns.ReadByte();

                            using (var ds = new DeflateStream(ns, CompressionMode.Decompress))
                            {
                                var prevLine = new byte[Width];                                          // all zero
                                for (var y = 0; y < Height; y++)
                                {
                                    var filter = (PngFilter)ds.ReadByte();
                                    var line   = ds.ReadBytes(Width);

                                    for (var i = 0; i < Width; i++)
                                    {
                                        line[i] = i > 0
                                                                                                ? UnapplyFilter(filter, line[i], line[i - 1], prevLine[i], prevLine[i - 1])
                                                                                                : UnapplyFilter(filter, line[i], 0, prevLine[i], 0);
                                    }

                                    Array.Copy(line, 0, Data, y * Width, line.Length);
                                    prevLine = line;
                                }
                            }
                        }

                        if (Palette == null)
                        {
                            throw new InvalidDataException("Non-Palette indexed PNG are not supported.");
                        }

                        return;
                    }
                    }
                }
            }
        }