예제 #1
0
        private static int Codes(BitStream bitStream, Huffman lencode, Huffman distcode, bool lastBlock)
        {
            int symbol;

            do
            {
                symbol = Decode(bitStream, lencode);
                if (symbol < 0)
                {
                    throw new ArgumentOutOfRangeException("invalid symbol.");
                }
                if (symbol < 256)
                {
                    bitStream.OutBuffer.Add((byte)symbol);
                    //bitStream.OutBufferWithHeader.Add((byte)symbol);
                    //if (bitStream.OutBuffer.Count() % 65535 == 0)
                    //{
                    //    Console.WriteLine("blocked");
                    //    var blocks = bitStream.OutBuffer.Count() / 65535;
                    //    bitStream.OutBufferWithHeader.InsertRange((65535 + 5) * (blocks - 1), BlockHeader(65535, false));
                    //}
                }
                else if (symbol > 256)
                {
                    symbol -= 257;
                    if (symbol >= 29)
                    {
                        throw new Exception("Invalid fixed code.");
                    }
                    var len = lens[symbol] + bitStream.GetNextBitsReverse(lext[symbol]);

                    symbol = Decode(bitStream, distcode);
                    if (symbol < 0)
                    {
                        throw new ArgumentOutOfRangeException("invalid symbol.");
                    }
                    var dist = dists[symbol] + bitStream.GetNextBitsReverse(dext[symbol]);

                    // copy length bytes from distance bytes back.
                    for (int i = 0; i < len; i++)
                    {
                        bitStream.OutBuffer.Add(bitStream.OutBuffer[bitStream.OutBuffer.Count() - dist]);
                        //bitStream.OutBufferWithHeader.Add(bitStream.OutBuffer[bitStream.OutBuffer.Count() - dist]);
                        //if (bitStream.OutBuffer.Count() % 65535 == 0)
                        //{
                        //    Console.WriteLine("blocked");
                        //    var blocks = bitStream.OutBuffer.Count() / 65535;
                        //    bitStream.OutBufferWithHeader.InsertRange((65535 + 5) * (blocks - 1), BlockHeader(65535, false));
                        //}
                    }
                }
            } while (symbol != 256);

            //if (lastBlock)
            //{
            //    var blocks = bitStream.OutBuffer.Count() / 65535;
            //    bitStream.OutBufferWithHeader.InsertRange((65535 + 5) * (blocks - 1), BlockHeader((ushort)(bitStream.OutBuffer.Count() % 65535), true));
            //}

            return(0);
        }
예제 #2
0
        static void Decode(ref PNG png)
        {
            Console.WriteLine($"\nDecoding zlib blocks...");
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();

            uint idatLength = 0;

            foreach (var chunk in png.IDATList)
            {
                idatLength += chunk.ChunkLength;
            }

            byte[] idatData = new byte[idatLength];

            var offset = 0;

            for (int i = 0; i < png.IDATList.Count(); i++)
            {
                Array.Copy(png.IDATList[i].ChunkData, 0, idatData, offset, (int)png.IDATList[i].ChunkLength);
                offset += (int)png.IDATList[i].ChunkLength;
            }

            Stream idatStream = new MemoryStream(idatData);
            var    zlibHeader = new byte[2];

            idatStream.Read(zlibHeader, 0, 2);

            var bitBuffer = new byte[idatLength - 6]; // subtract 2 byte zlib header and 4 byte adler checksum.

            idatStream.Read(bitBuffer, 0, (int)(idatLength - 6));
            idatStream.Dispose();
            BitArray  bitArray = new BitArray(bitBuffer);
            BitStream bs       = new BitStream(bitArray);

            bool lastBlock;
            byte compression;

            do
            {
                lastBlock   = bs.GetNextBitsReverse(1) == 1;
                compression = (byte)bs.GetNextBitsReverse(2);

                if (compression == 0)
                {
                    Console.WriteLine($"Zlib block already uncompressed...");
                    bs.GetNextBitsReverse(5);
                    ushort len = bs.GetNextShortReverse();
                    ushort nen = (ushort)~bs.GetNextShortReverse();
                    if (nen != len)
                    {
                        throw new Exception("Nen does not complement Len.");
                    }
                    for (int i = 0; i < len; i++)
                    {
                        bs.GetNextBitsReverse(8);
                    }
                }
                else if (compression == 1)
                {
                    Console.WriteLine($"Uncompressing {(lastBlock ? "last " : "")}zlib block...");
                    Puff.ParseFixed(bs, lastBlock);
                }
                else if (compression == 2)
                {
                    Console.WriteLine($"Uncompressing {(lastBlock ? "last " : "")}zlib block...");
                    Puff.ParseDynamic(bs, lastBlock);
                }
            }while (lastBlock == false);

            if (compression != 0)
            {
                var adler = new Adler32();
                adler.Update(bs.OutBuffer.ToArray());
                byte[] adlerbytearray = BitConverter.GetBytes((int)adler.Value);
                Array.Reverse(adlerbytearray, 0, adlerbytearray.Length);

                Console.WriteLine($"Adler32 checksum = {adlerbytearray[0]} {adlerbytearray[1]} {adlerbytearray[2]} {adlerbytearray[3]}");

                var numblocks    = (bs.OutBuffer.Count()) / 65500;
                var numblocksRem = (bs.OutBuffer.Count()) % 65500;

                var splitBlocklist = new List <byte>();

                if (numblocks > 0)
                {
                    for (int j = 0; j < numblocks; j++)
                    {
                        InsertBlockHeader(splitBlocklist, 65500, false);
                        for (int i = 0; i < 65500; i++)
                        {
                            splitBlocklist.Add(bs.OutBuffer[i + j * 65500]);
                        }
                    }
                    InsertBlockHeader(splitBlocklist, (ushort)numblocksRem, true);
                    for (int i = (int)(bs.OutBuffer.Count() - numblocksRem); i < (bs.OutBuffer.Count()); i++)
                    {
                        splitBlocklist.Add(bs.OutBuffer[i]);
                    }
                }
                else
                {
                    InsertBlockHeader(splitBlocklist, (ushort)numblocksRem, true);
                    for (int i = (int)(bs.OutBuffer.Count() - numblocksRem); i < (bs.OutBuffer.Count()); i++)
                    {
                        splitBlocklist.Add(bs.OutBuffer[i]);
                    }
                }

                for (int i = 0; i < adlerbytearray.Length; i++)
                {
                    splitBlocklist.Add(adlerbytearray[i]);
                }

                byte[] newChunkData = new byte[splitBlocklist.Count() + 2];
                zlibHeader.CopyTo(newChunkData, 0);
                splitBlocklist.ToArray().CopyTo(newChunkData, 2);

                var ncdChunks = newChunkData.Length / 65500;
                var ncdRem    = newChunkData.Length % 65500;

                png.IDATList.Clear();

                for (int i = 0; i < ncdChunks; i++)
                {
                    IDATChunk newIdatChunk = new IDATChunk();
                    newIdatChunk.ChunkData = newChunkData.SubArray(i * 65500, 65500);
                    png.IDATList.Add(newIdatChunk);
                }

                IDATChunk finalIdatChunk = new IDATChunk();
                finalIdatChunk.ChunkData = newChunkData.SubArray(newChunkData.Length - ncdRem, ncdRem);
                png.IDATList.Add(finalIdatChunk);
            }

            stopWatch.Stop();
            string elapsedTime = stopWatch.Elapsed.FormatTime();

            Console.WriteLine($"Total decode time = {elapsedTime}");
        }
예제 #3
0
        public static int ParseDynamic(BitStream bitStream, bool lastBlock)
        {
            short[] lengths = new short[MAXCODES];

            int nlen  = bitStream.GetNextBitsReverse(5) + 257;
            int ndist = bitStream.GetNextBitsReverse(5) + 1;
            int ncode = bitStream.GetNextBitsReverse(4) + 4;

            if (nlen > MAXLCODES || ndist > MAXDCODES)
            {
                throw new Exception("bad counts");
            }

            for (int i = 0; i < ncode; i++)
            {
                lengths[order[i]] = (short)bitStream.GetNextBitsReverse(3);
            }
            for (int i = ncode; i < 19; i++)
            {
                lengths[order[i]] = 0;
            }

            //for (int i = 0; i < lengths.Length; i++)
            //{
            //    Console.WriteLine($"symbol {i} has a code length of {lengths[i]}");
            //}

            var lencode  = new Huffman(new short[MAXBITS + 1], new short[MAXLCODES]);
            var distcode = new Huffman(new short[MAXBITS + 1], new short[MAXDCODES]);

            var err = Construct(ref lencode, lengths, 19);

            if (err != 0)
            {
                throw new Exception("complete code set required here; code lengths codes incomplete.");
            }

            //for (int i = 0; i < lencode.count.Length; i++)
            //{
            //    Console.WriteLine($"{lencode.count[i]} symbols of length {i}");
            //}

            var index = 0;

            while (index < nlen + ndist)
            {
                var symbol = Decode(bitStream, lencode);
                var len    = 0;

                if (symbol < 0)
                {
                    throw new ArgumentOutOfRangeException("invalid symbol");
                }
                if (symbol < 16)
                {
                    lengths[index++] = (short)symbol;
                }
                else
                {
                    if (symbol == 16)
                    {
                        if (index == 0)
                        {
                            throw new ArgumentOutOfRangeException("no preceeding length to reference!");
                        }
                        len    = lengths[index - 1];
                        symbol = 3 + bitStream.GetNextBitsReverse(2);
                    }
                    else if (symbol == 17)
                    {
                        symbol = 3 + bitStream.GetNextBitsReverse(3);
                    }
                    else
                    {
                        symbol = 11 + bitStream.GetNextBitsReverse(7);
                    }
                    if (index + symbol > nlen + ndist)
                    {
                        throw new ArgumentOutOfRangeException("too many lengths!");
                    }
                    while (symbol-- > 0)
                    {
                        lengths[index++] = (short)len;
                    }
                }
            }

            if (lengths[256] == 0)
            {
                throw new Exception("no end of block code");
            }

            err = Construct(ref lencode, lengths, nlen);
            if (err != 0 & (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
            {
                throw new ArgumentException("incomplete code ok only for single length 1 code.");
            }

            var _lengths = new short[MAXDCODES];

            Array.Copy(lengths, nlen, _lengths, 0, MAXDCODES);

            err = Construct(ref distcode, _lengths, ndist);
            if (err != 0 & (err < 0 || nlen != distcode.count[0] + distcode.count[1]))
            {
                throw new ArgumentException("incomplete code ok only for single length 1 code.");
            }

            return(Codes(bitStream, lencode, distcode, lastBlock));
        }