Beispiel #1
0
        /* Compress */
        public static MemoryStream Compress(ref Stream data, string filename)
        {
            try
            {
                var decompressedSize = (uint)data.Length;

                var compressedData = new MemoryStream();
                byte[] decompressedData = data.ToByteArray();

                uint sourcePointer = 0x0;
                uint destPointer = 0x4;

                // Test if the file is too large to be compressed
                if (data.Length > 0xFFFFFF)
                    throw new Exception("Input file is too large to compress.");

                // Set up the Lz Compression Dictionary
                var lzDictionary = new LzWindowDictionary();
                lzDictionary.SetWindowSize(0x1000);
                lzDictionary.SetMaxMatchAmount(0xF + 3);

                // Start compression
                compressedData.Write('\x10' | (decompressedSize << 8));
                while (sourcePointer < decompressedSize)
                {
                    byte flag = 0x0;
                    var flagPosition = destPointer;
                    compressedData.WriteByte(flag); // It will be filled in later
                    destPointer++;

                    for (var i = 7; i >= 0; i--)
                    {
                        var lzSearchMatch = lzDictionary.Search(decompressedData, sourcePointer, decompressedSize);
                        if (lzSearchMatch[1] > 0) // There is a compression match
                        {
                            flag |= (byte)(1 << i);

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

                            lzDictionary.AddEntryRange(decompressedData, (int)sourcePointer, lzSearchMatch[1]);
                            lzDictionary.SlideWindow(lzSearchMatch[1]);

                            sourcePointer += (uint)lzSearchMatch[1];
                            destPointer += 2;
                        }
                        else // There wasn't a match
                        {
                            flag |= (byte)(0 << i);

                            compressedData.WriteByte(decompressedData[sourcePointer]);

                            lzDictionary.AddEntry(decompressedData, (int)sourcePointer);
                            lzDictionary.SlideWindow(1);

                            sourcePointer++;
                            destPointer++;
                        }

                        // Check for out of bounds
                        if (sourcePointer >= decompressedSize)
                            break;
                    }

                    // Write the flag.
                    // The original position gets reset after writing.
                    compressedData.Seek(flagPosition, SeekOrigin.Begin);
                    compressedData.WriteByte(flag);
                    compressedData.Seek(destPointer, SeekOrigin.Begin);
                }

                return compressedData;
            }
            catch
            {
                return null; // An error occured while compressing
            }
        }
Beispiel #2
0
        /* Compress */
        public static MemoryStream Compress(ref Stream data, string filename)
        {
            try
            {
                var decompressedSize = (uint)data.Length;

                var    compressedData   = new MemoryStream();
                byte[] decompressedData = data.ToByteArray();

                uint sourcePointer = 0x0;
                uint destPointer   = 0x4;

                // Test if the file is too large to be compressed
                if (data.Length > 0xFFFFFF)
                {
                    throw new Exception("Input file is too large to compress.");
                }

                // Set up the Lz Compression Dictionary
                var lzDictionary = new LzWindowDictionary();
                lzDictionary.SetWindowSize(0x1000);
                lzDictionary.SetMaxMatchAmount(0xF + 3);

                // Start compression
                compressedData.Write('\x10' | (decompressedSize << 8));
                while (sourcePointer < decompressedSize)
                {
                    byte flag         = 0x0;
                    var  flagPosition = destPointer;
                    compressedData.WriteByte(flag); // It will be filled in later
                    destPointer++;

                    for (var i = 7; i >= 0; i--)
                    {
                        var lzSearchMatch = lzDictionary.Search(decompressedData, sourcePointer, decompressedSize);
                        if (lzSearchMatch[1] > 0) // There is a compression match
                        {
                            flag |= (byte)(1 << i);

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

                            lzDictionary.AddEntryRange(decompressedData, (int)sourcePointer, lzSearchMatch[1]);
                            lzDictionary.SlideWindow(lzSearchMatch[1]);

                            sourcePointer += (uint)lzSearchMatch[1];
                            destPointer   += 2;
                        }
                        else // There wasn't a match
                        {
                            flag |= (byte)(0 << i);

                            compressedData.WriteByte(decompressedData[sourcePointer]);

                            lzDictionary.AddEntry(decompressedData, (int)sourcePointer);
                            lzDictionary.SlideWindow(1);

                            sourcePointer++;
                            destPointer++;
                        }

                        // Check for out of bounds
                        if (sourcePointer >= decompressedSize)
                        {
                            break;
                        }
                    }

                    // Write the flag.
                    // The original position gets reset after writing.
                    compressedData.Seek(flagPosition, SeekOrigin.Begin);
                    compressedData.WriteByte(flag);
                    compressedData.Seek(destPointer, SeekOrigin.Begin);
                }

                return(compressedData);
            }
            catch
            {
                return(null); // An error occured while compressing
            }
        }