public static byte[] Compress(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } using (var output = new MemoryStream()) { // ZLib Header 0x78 0x9C output.WriteByte(0x78); output.WriteByte(0x9C); using (var input = new MemoryStream(data)) { using (var compressionStream = new DeflateStream(output, CompressionMode.Compress, true)) { input.CopyTo(compressionStream); compressionStream.Close(); // Adler32 hash of the uncompressed data var adler32 = new Adler32(); adler32.Update(data); byte[] hash = BitConverter.GetBytes((int) adler32.Value); Array.Reverse(hash); output.Write(hash, 0, hash.Length); return output.ToArray(); } } } }
private static void WriteDataChunksFast() { byte[] pixels = _image.ToByteArray(); // Convert the pixel array to a new array for adding // the filter byte. // -------------------------------------------------- byte[] data = new byte[_image.PixelWidth * _image.PixelHeight * 4 + _image.PixelHeight]; int rowLength = _image.PixelWidth * 4 + 1; for (int y = 0; y < _image.PixelHeight; y++) { data[y * rowLength] = 0; Array.Copy(pixels, y * _image.PixelWidth * 4, data, y * rowLength + 1, _image.PixelWidth * 4); } // -------------------------------------------------- Adler32 adler32 = new Adler32(); adler32.Update(data); using (MemoryStream tempStream = new MemoryStream()) { int remainder = data.Length; int blockCount; if ((data.Length % MaxBlockSize) == 0) { blockCount = data.Length / MaxBlockSize; } else { blockCount = (data.Length / MaxBlockSize) + 1; } // Write headers tempStream.WriteByte(0x78); tempStream.WriteByte(0xDA); for (int i = 0; i < blockCount; i++) { // Write the length ushort length = (ushort)((remainder < MaxBlockSize) ? remainder : MaxBlockSize); if (length == remainder) { tempStream.WriteByte(0x01); } else { tempStream.WriteByte(0x00); } tempStream.Write(BitConverter.GetBytes(length), 0, 2); // Write one's compliment of length tempStream.Write(BitConverter.GetBytes((ushort)~length), 0, 2); // Write blocks tempStream.Write(data, (int)(i * MaxBlockSize), length); // Next block remainder -= MaxBlockSize; } WriteInteger(tempStream, (int)adler32.Value); tempStream.Seek(0, SeekOrigin.Begin); byte[] zipData = new byte[tempStream.Length]; tempStream.Read(zipData, 0, (int)tempStream.Length); WriteChunk(PngChunkTypes.Data, zipData); } }
internal static void Run() { const int iterations = 0x20000; const int testSize = 0x10000; List<long> timeMurmur = new List<long>(iterations); List<long> timeAdler = new List<long>(iterations); List<long> timeMd5 = new List<long>(iterations); byte[] randBytes = new byte[testSize]; var rnd = new Random(); var watchMurmur = new Stopwatch(); var watchAdler = new Stopwatch(); var watchMd5 = new Stopwatch(); bool dry = true; DoRun: for (int i = 0; i < iterations; i++) { rnd.NextBytes(randBytes); { var murmur = Murmur128.CreateMurmur(); watchMurmur.Restart(); murmur.ComputeHash(randBytes); watchMurmur.Stop(); if (!dry) timeMurmur.Add(watchMurmur.ElapsedTicks); } { var adler = new Adler32(); watchAdler.Restart(); adler.Update(randBytes); watchAdler.Stop(); if (!dry) timeAdler.Add(watchAdler.ElapsedTicks); } { var md5 = MD5.Create(); watchMd5.Restart(); md5.ComputeHash(randBytes); watchMd5.Stop(); if (!dry) timeMd5.Add(watchMd5.ElapsedTicks); } if (i == 0x1000 && dry) { dry = false; goto DoRun; } } var avgMurmur = TimeSpan.FromTicks(Convert.ToInt64(timeMurmur.Average())); var avgAdler = TimeSpan.FromTicks(Convert.ToInt64(timeAdler.Average())); var avgMd5 = TimeSpan.FromTicks(Convert.ToInt64(timeMd5.Average())); Console.WriteLine("Average murmur:\t" + avgMurmur); Console.WriteLine("Average adler:\t" + avgAdler); Console.WriteLine("Average md5:\t" + avgMd5); Console.ReadKey(); }