Esempio n. 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
        }
    }
Esempio n. 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
            }
    }