/// <summary>
        /// Compress data from a stream.
        /// </summary>
        /// <param name="source">The stream to read from.</param>
        /// <param name="destination">The stream to write to.</param>
        public override void Compress(Stream source, Stream destination)
        {
            // Get the source length
            int sourceLength = (int)(source.Length - source.Position);

            // Read the source data into an array
            byte[] sourceArray = new byte[sourceLength];
            source.Read(sourceArray, 0, sourceLength);

            // Set the source and destination pointers
            int sourcePointer = 0x0;
            int destinationPointer = 0x4;

            // Initalize the LZ dictionary
            LzWindowDictionary dictionary = new LzWindowDictionary();
            dictionary.SetWindowSize(0x1000);
            dictionary.SetMaxMatchAmount(0x1000);

            // Write out the header
            // Magic code & decompressed length
            if (sourceLength <= 0xFFFFFF)
            {
                PTStream.WriteInt32(destination, 0x11 | (sourceLength << 8));
            }
            else
            {
                destination.WriteByte(0x11);
                PTStream.WriteInt32(destination, sourceLength);

                destinationPointer += 4;
            }

            // Start compression
            while (sourcePointer < sourceLength)
            {
                using (MemoryStream buffer = new MemoryStream())
                {
                    byte flag = 0;

                    for (int i = 7; i >= 0; i--)
                    {
                        // Search for a match
                        int[] match = dictionary.Search(sourceArray, (uint)sourcePointer, (uint)sourceLength);

                        if (match[1] > 0) // There is a match
                        {
                            flag |= (byte)(1 << i);

                            // How many bytes will the match take up?
                            if (match[1] <= 0xF + 1) // 2 bytes
                            {
                                buffer.WriteByte((byte)((((match[1] - 1) & 0xF) << 4) | (((match[0] - 1) & 0xFFF) >> 8)));
                                buffer.WriteByte((byte)((match[0] - 1) & 0xFF));
                            }
                            else if (match[1] <= 0xFF + 17) // 3 bytes
                            {
                                buffer.WriteByte((byte)(((match[1] - 17) & 0xFF) >> 4));
                                buffer.WriteByte((byte)((((match[1] - 17) & 0xF) << 4) | (((match[0] - 1) & 0xFFF) >> 8)));
                                buffer.WriteByte((byte)((match[0] - 1) & 0xFF));
                            }
                            else // 4 bytes
                            {
                                buffer.WriteByte((byte)(0x10 | (((match[1] - 273) & 0xFFFF) >> 12)));
                                buffer.WriteByte((byte)(((match[1] - 273) & 0xFFF) >> 4));
                                buffer.WriteByte((byte)((((match[1] - 273) & 0xF) << 4) | (((match[0] - 1) & 0xFFF) >> 8)));
                                buffer.WriteByte((byte)((match[0] - 1) & 0xFF));
                            }

                            dictionary.AddEntryRange(sourceArray, sourcePointer, match[1]);
                            dictionary.SlideWindow(match[1]);

                            sourcePointer += match[1];
                        }
                        else // There is not a match
                        {
                            buffer.WriteByte(sourceArray[sourcePointer]);

                            dictionary.AddEntry(sourceArray, sourcePointer);
                            dictionary.SlideWindow(1);

                            sourcePointer++;
                        }

                        // Check to see if we reached the end of the file
                        if (sourcePointer >= sourceLength)
                            break;
                    }

                    // Flush the buffer and write it to the destination stream
                    destination.WriteByte(flag);

                    buffer.Position = 0;
                    while (buffer.Position < buffer.Length)
                    {
                        byte value = PTStream.ReadByte(buffer);
                        destination.WriteByte(value);
                    }

                    destinationPointer += (int)buffer.Length + 1;
                }
            }
        }
        public void Compress(Stream source, Stream destination, bool fast)
        {
            int sourceLength = (int)(source.Length - source.Position);

            // Read the source data into an array
            byte[] sourceArray = new byte[sourceLength];
            source.Read(sourceArray, 0, sourceLength);

            // Set the source and destination pointers
            int sourcePointer      = 0x0;
            int destinationPointer = 0x4;

            // Initalize the LZ dictionary
            LzWindowDictionary dictionary = new LzWindowDictionary();

            if (fast)
            {
                dictionary.SetWindowSize(3);
                dictionary.SetMaxMatchAmount(3);
            }
            else
            {
                dictionary.SetWindowSize(0x10);
                dictionary.SetMaxMatchAmount(0x10);
            }

            // Write out the header
            // Magic code & decompressed length
            if (sourceLength <= 0xFFFFFF)
            {
                PTStream.WriteInt32(destination, 0x11 | (sourceLength << 8));
            }
            else
            {
                destination.WriteByte(0x11);
                PTStream.WriteInt32(destination, sourceLength);

                destinationPointer += 4;
            }

            // Start compression
            while (sourcePointer < sourceLength)
            {
                using (MemoryStream buffer = new MemoryStream())
                {
                    byte flag = 0;

                    for (int i = 7; i >= 0; i--)
                    {
                        // Search for a match
                        int[] match = dictionary.Search(sourceArray, (uint)sourcePointer, (uint)sourceLength);

                        if (match[1] > 0) // There is a match
                        {
                            flag |= (byte)(1 << i);

                            // How many bytes will the match take up?
                            if (match[1] <= 0xF + 1) // 2 bytes
                            {
                                buffer.WriteByte((byte)((((match[1] - 1) & 0xF) << 4) | (((match[0] - 1) & 0xFFF) >> 8)));
                                buffer.WriteByte((byte)((match[0] - 1) & 0xFF));
                            }
                            else if (match[1] <= 0xFF + 17) // 3 bytes
                            {
                                buffer.WriteByte((byte)(((match[1] - 17) & 0xFF) >> 4));
                                buffer.WriteByte((byte)((((match[1] - 17) & 0xF) << 4) | (((match[0] - 1) & 0xFFF) >> 8)));
                                buffer.WriteByte((byte)((match[0] - 1) & 0xFF));
                            }
                            else // 4 bytes
                            {
                                buffer.WriteByte((byte)(0x10 | (((match[1] - 273) & 0xFFFF) >> 12)));
                                buffer.WriteByte((byte)(((match[1] - 273) & 0xFFF) >> 4));
                                buffer.WriteByte((byte)((((match[1] - 273) & 0xF) << 4) | (((match[0] - 1) & 0xFFF) >> 8)));
                                buffer.WriteByte((byte)((match[0] - 1) & 0xFF));
                            }

                            dictionary.AddEntryRange(sourceArray, sourcePointer, match[1]);
                            dictionary.SlideWindow(match[1]);

                            sourcePointer += match[1];
                        }
                        else // There is not a match
                        {
                            buffer.WriteByte(sourceArray[sourcePointer]);

                            dictionary.AddEntry(sourceArray, sourcePointer);
                            dictionary.SlideWindow(1);

                            sourcePointer++;
                        }

                        // Check to see if we reached the end of the file
                        if (sourcePointer >= sourceLength)
                        {
                            break;
                        }
                    }

                    // Flush the buffer and write it to the destination stream
                    destination.WriteByte(flag);

                    buffer.Position = 0;
                    while (buffer.Position < buffer.Length)
                    {
                        byte value = PTStream.ReadByte(buffer);
                        destination.WriteByte(value);
                    }

                    destinationPointer += (int)buffer.Length + 1;
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Compress data from a stream.
        /// </summary>
        /// <param name="source">The stream to read from.</param>
        /// <param name="destination">The stream to write to.</param>
        public override void Compress(Stream source, Stream destination)
        {
            // Get the source length
            int sourceLength = (int)(source.Length - source.Position);

            // LZ10 compression can only handle files smaller than 16MB
            if (sourceLength > 0xFFFFFF)
            {
                throw new Exception("Source is too large. LZ10 compression can only compress files smaller than 16MB.");
            }

            // Read the source data into an array
            byte[] sourceArray = new byte[sourceLength];
            source.Read(sourceArray, 0, sourceLength);

            // Set the source and destination pointers
            int sourcePointer      = 0x0;
            int destinationPointer = 0x4;

            // Initalize the LZ dictionary
            LzWindowDictionary dictionary = new LzWindowDictionary();

            dictionary.SetWindowSize(0x1000);
            dictionary.SetMaxMatchAmount(0xF + 3);

            // Write out the header
            // Magic code & decompressed length
            PTStream.WriteInt32(destination, 0x10 | (sourceLength << 8));

            // Start compression
            while (sourcePointer < sourceLength)
            {
                using (MemoryStream buffer = new MemoryStream())
                {
                    byte flag = 0;

                    for (int i = 7; i >= 0; i--)
                    {
                        // Search for a match
                        int[] match = dictionary.Search(sourceArray, (uint)sourcePointer, (uint)sourceLength);

                        if (match[1] > 0) // There is a match
                        {
                            flag |= (byte)(1 << i);

                            buffer.WriteByte((byte)((((match[1] - 3) & 0xF) << 4) | (((match[0] - 1) & 0xFFF) >> 8)));
                            buffer.WriteByte((byte)((match[0] - 1) & 0xFF));

                            dictionary.AddEntryRange(sourceArray, sourcePointer, match[1]);
                            dictionary.SlideWindow(match[1]);

                            sourcePointer += match[1];
                        }
                        else // There is not a match
                        {
                            buffer.WriteByte(sourceArray[sourcePointer]);

                            dictionary.AddEntry(sourceArray, sourcePointer);
                            dictionary.SlideWindow(1);

                            sourcePointer++;
                        }

                        // Check to see if we reached the end of the file
                        if (sourcePointer >= sourceLength)
                        {
                            break;
                        }
                    }

                    // Flush the buffer and write it to the destination stream
                    destination.WriteByte(flag);

                    buffer.Position = 0;
                    while (buffer.Position < buffer.Length)
                    {
                        byte value = PTStream.ReadByte(buffer);
                        destination.WriteByte(value);
                    }

                    destinationPointer += (int)buffer.Length + 1;
                }
            }
        }