Beispiel #1
0
        private void Handle_IDAT(PNGChunk chunk)
        {
            IDATChunk idatC = new IDATChunk();

            idatC.ChunkData = chunk.ChunkData;
            IDATList.Add(idatC);
        }
Beispiel #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}");
        }