public void HuffmanCompressUncompressTest() { var ThisEncoding = Encoding.UTF8; var InputString = "Hola. Esto es una prueba para ver si funciona la compresión Huffman."; var InputBytes = ThisEncoding.GetBytes(InputString); var InputStream = new MemoryStream(InputBytes); var InputUsageTable = Huffman.CalculateUsageTable(InputBytes); var InputEncodingTable = Huffman.BuildTable(InputUsageTable); var CompressedStream = Huffman.Compress(InputStream, InputEncodingTable); var DecompressedStream = Huffman.Uncompress(CompressedStream, (uint)InputBytes.Length, InputEncodingTable); var DecompressedBytes = DecompressedStream.ReadAll(); var DecompressedString = ThisEncoding.GetString(DecompressedBytes); Assert.AreEqual(InputString, DecompressedString); }
//public Queue<byte[]> GetQTreeCompressed(int frame_limit, int from_revision) public Queue <byte[]> GetQTreeCompressed(int frame_limit, int from_revision) { frame_limit--; // reservo el espacio para el 0xAC (cierre) var result = new Queue <byte[]>(); var dataset = GetActionsQueue(from_revision); var data_buffer = new byte[frame_limit + 1]; var db_cursor = 0; var pagina = 0; var huffman_sectors = 0; var rle_sectors = 0; var uncompresed_sectors = 0; var total_sectors = 0; const int adds = 0; byte operaciones = 0; var operaciones_en_pagina = 0; var source_size = 0; // preparo el espacio pata operaciones. UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0); var total_de_pasos = dataset.Count; var pasos = 0; foreach (var action in dataset) { pasos++; var completado = pasos * 100.0 / total_de_pasos; if (pasos % 5000 == 0) { STrace.Debug(GetType().FullName, String.Format("QTREE/GETQTREECOMPRESSED: {0:0.0}% completado.", completado)); } if (operaciones_en_pagina > Hacker.QTree.OperacionesPorPagina) { UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0xAC); // Cierre del bloque source_size++; operaciones++; operaciones_en_pagina = 0; pagina++; //Marshall.User("QTREE: un OPERACIONXPAGINA cerro msg {0} de {1} bytes y {2} operaciones", pagina, db_cursor, operaciones); var transient = new byte[db_cursor]; var dummy = 0; Array.Copy(data_buffer, transient, db_cursor); // Actualizo las operaciones en el bloque. UrbetrackCodec.EncodeByte(ref transient, ref dummy, operaciones); result.Enqueue(transient); db_cursor = 0; operaciones = 0; // preparo el espacio pata operaciones. UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0); } switch (action.Action) { case QtreeAction.Actions.START_UPDATE: //Marshall.User(String.Format("QTREE:MSG={0}/START={1}/SIZE={2}: FULL FORMAT", pagina, db_cursor, 5)); source_size += 5; operaciones_en_pagina++; // 0xFF es Full Format. UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0xFF); // Patron de Seguridad. UrbetrackCodec.EncodeInteger(ref data_buffer, ref db_cursor, action.Sector); operaciones++; break; case QtreeAction.Actions.SET_GR2_DEFAULTS: if (db_cursor + 8 > frame_limit) { //Marshall.User(String.Format("QTREE:MSG={0}/START={1}/SIZE={2}: CLOSE PAGE", pagina, db_cursor, 1)); UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0xAC); // Cierre del bloque source_size++; operaciones++; operaciones_en_pagina = 0; pagina++; //Marshall.User("QTREE: un UPDATE_REVISION cerro msg {0} de {1} bytes y {2} operaciones", pagina, db_cursor, operaciones); var transient = new byte[db_cursor]; var dummy = 0; Array.Copy(data_buffer, transient, db_cursor); // Actualizo las operaciones en el bloque. UrbetrackCodec.EncodeByte(ref transient, ref dummy, operaciones); result.Enqueue(transient); db_cursor = 0; operaciones = 0; // preparo el espacio pata operaciones. UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0); } // 0xDF es DeFaults UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0xDF); UrbetrackCodec.EncodeShort(ref data_buffer, ref db_cursor, action.FileLat); UrbetrackCodec.EncodeShort(ref data_buffer, ref db_cursor, action.FileLon); UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, (byte)action.Sector); operaciones++; break; case QtreeAction.Actions.SET_M2: { byte repeated_byte = 0; var sector = GetSector(action.Filename, action.Sector, ref repeated_byte); var file_class = (byte)matrix[action.Filename][5000]; if (repeated_byte != 0 && repeated_byte == file_class) { STrace.Debug(GetType().FullName, String.Format("QTREE/FILE[{0}]: saltando sector x defecto {1} class={2}", action.Filename, action.Sector, file_class)); continue; } source_size += 512; var page_buffer = new byte[512]; var page_cursor = 0; UrbetrackCodec.EncodeByte(ref page_buffer, ref page_cursor, 0x01); UrbetrackCodec.EncodeShort(ref page_buffer, ref page_cursor, action.FileLat); UrbetrackCodec.EncodeShort(ref page_buffer, ref page_cursor, action.FileLon); UrbetrackCodec.EncodeInteger(ref page_buffer, ref page_cursor, action.Sector); var huff = new Huffman(); var result_huffman = huff.Compress(sector, 0, 512); var rle = new RLE(); var result_rle = rle.Compress(sector, 0, 512); byte[] compressed_data; if (sector.GetLength(0) <= result_huffman.GetLength(0) && sector.GetLength(0) <= result_rle.GetLength(0)) { uncompresed_sectors++; compressed_data = sector; UrbetrackCodec.EncodeShort(ref page_buffer, ref page_cursor, (short)compressed_data.GetLength(0)); UrbetrackCodec.EncodeByte(ref page_buffer, ref page_cursor, 0x00); // indicador de algoritmo (Sin compresion) } else if (result_huffman.GetLength(0) <= sector.GetLength(0) && result_huffman.GetLength(0) <= result_rle.GetLength(0)) { huffman_sectors++; compressed_data = result_huffman; UrbetrackCodec.EncodeShort(ref page_buffer, ref page_cursor, (short)compressed_data.GetLength(0)); UrbetrackCodec.EncodeByte(ref page_buffer, ref page_cursor, 0x02); // indicador de algoritmo (Huffman) } else if (result_rle.GetLength(0) <= result_huffman.GetLength(0) && result_rle.GetLength(0) <= sector.GetLength(0)) { rle_sectors++; compressed_data = result_rle; UrbetrackCodec.EncodeShort(ref page_buffer, ref page_cursor, (short)compressed_data.GetLength(0)); UrbetrackCodec.EncodeByte(ref page_buffer, ref page_cursor, 0x01); // indicador de algoritmo (RLE) } else { STrace.Debug(GetType().FullName, "QTREE: imposible elijir algoritmo."); return(null); } // agrego el buffer de datos... UrbetrackCodec.EncodeBytes(ref page_buffer, ref page_cursor, compressed_data); // valido si es posible meter el buffer en una sola pagina al menos. if (page_cursor > frame_limit) { STrace.Debug(GetType().FullName, "QTREE: el resultado de una pagina no entra en el buffer completo."); STrace.Debug(GetType().FullName, "QTREE: el resultado de una pagina no entra en el buffer completo."); return(null); } // ahora tengo que validar si me entra en esta pagina, o la cierro y empiezo otra. if (db_cursor + page_cursor > frame_limit) { //Marshall.User(String.Format("QTREE:MSG={0}/START={1}/SIZE={2}: CLOSE PAGE", pagina, db_cursor, 1)); UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0xAC); // Cierre del bloque source_size++; operaciones++; operaciones_en_pagina = 0; pagina++; //Marshall.User("QTREE: un SET_M2 cerro msg {0} de {1} bytes y {2} operaciones", pagina, db_cursor, operaciones); var transient = new byte[db_cursor]; var dummy = 0; Array.Copy(data_buffer, transient, db_cursor); // Actualizo las operaciones en el bloque. UrbetrackCodec.EncodeByte(ref transient, ref dummy, operaciones); result.Enqueue(transient); db_cursor = 0; operaciones = 0; // preparo el espacio pata operaciones. UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0); } Array.Copy(page_buffer, 0, data_buffer, db_cursor, page_cursor); //Marshall.User(String.Format("QTREE:MSG={0}/START={1}/SIZE={2}: SET {3};{4} PAGE:{5}", pagina, db_cursor, page_cursor, action.FileLat, action.FileLon, action.Sector)); db_cursor += page_cursor; total_sectors++; operaciones++; operaciones_en_pagina++; } break; case QtreeAction.Actions.UPDATE_REVISION: if (db_cursor + 5 > frame_limit) { //Marshall.User(String.Format("QTREE:MSG={0}/START={1}/SIZE={2}: CLOSE PAGE", pagina, db_cursor, 1)); UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0xAC); // Cierre del bloque source_size++; operaciones++; operaciones_en_pagina = 0; pagina++; //Marshall.User("QTREE: un UPDATE_REVISION cerro msg {0} de {1} bytes y {2} operaciones", pagina, db_cursor, operaciones); var transient = new byte[db_cursor]; var dummy = 0; Array.Copy(data_buffer, transient, db_cursor); // Actualizo las operaciones en el bloque. UrbetrackCodec.EncodeByte(ref transient, ref dummy, operaciones); result.Enqueue(transient); db_cursor = 0; operaciones = 0; // preparo el espacio pata operaciones. UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0); } //Marshall.User(String.Format("QTREE:MSG={0}/START={1}/SIZE={2}: UPDATE REVISION {3}", pagina, db_cursor, 5, action.Sector)); UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0x02); UrbetrackCodec.EncodeInteger(ref data_buffer, ref db_cursor, action.Sector); source_size += 5; operaciones++; operaciones_en_pagina++; break; } } { //Marshall.User(String.Format("QTREE:MSG={0}/START={1}/SIZE={2}: UPDATE FINISH", pagina, db_cursor, 1)); UrbetrackCodec.EncodeByte(ref data_buffer, ref db_cursor, 0xDC); // Fin de la actualizacion. var transient = new byte[db_cursor]; var dummy = 0; operaciones++; source_size += 1; //Marshall.User("QTREE: cerro la ultima pagina {0} de {1} bytes y {2} operaciones", pagina, db_cursor, operaciones); Array.Copy(data_buffer, transient, db_cursor); // Actualizo las operaciones en el bloque. UrbetrackCodec.EncodeByte(ref transient, ref dummy, operaciones); result.Enqueue(transient); } if (pagina == 0) { STrace.Debug(GetType().FullName, String.Format("QRTEE NO SE REQUIERE UPDATE revision {0}", from_revision)); return(null); } var suma_total = result.Sum(tmp => tmp.GetLength(0)); STrace.Debug(GetType().FullName, String.Format("QRTEE COMPRIMIDO entre revisiones {0} y {1}", from_revision, Revision)); STrace.Debug(GetType().FullName, "==================================================================================="); STrace.Debug(GetType().FullName, String.Format(" Tamaño Origninal: {0} bytes en {1} paginas.", source_size, total_sectors)); STrace.Debug(GetType().FullName, String.Format(" Tamaño Final: {0} bytes en {1} paginas. ({2} bytes pormedio por pagina)", suma_total, pagina, (pagina > 0 ? suma_total / pagina : 0))); STrace.Debug(GetType().FullName, String.Format(" Tasa de Compresion: {0}%", suma_total * 100 / source_size)); STrace.Debug(GetType().FullName, String.Format(" Paginas RAW: {0} ({1}%)", uncompresed_sectors, uncompresed_sectors * 100 / total_sectors)); STrace.Debug(GetType().FullName, String.Format(" Paginas RLE: {0} ({1}%)", rle_sectors, rle_sectors * 100 / total_sectors)); STrace.Debug(GetType().FullName, String.Format(" Paginas HUFFMAN: {0} ({1}%)", huffman_sectors, huffman_sectors * 100 / total_sectors)); STrace.Debug(GetType().FullName, String.Format(" GR2 Agreagados: {0}", adds)); return(result); }
public static void Compress(object sender, EventArgs e) { var tsi = sender as ToolStripMenuItem; if (!PrepareFiles("Open a decompressed " + tsi.Tag.ToString() + "file...", "Save your compressed file...", ".comp", out FileStream openFile, out FileStream saveFile)) { return; } try { using (openFile) using (var outFs = new BinaryWriterX(saveFile)) switch (tsi.Tag) { /*case Compression.L5LZSS: * outFs.Write(Level5.Compress(openFile, 1)); * break; * case Compression.L5Huff4: * outFs.Write(Level5.Compress(openFile, 2)); * break; * case Compression.L5Huff8: * outFs.Write(Level5.Compress(openFile, 3)); * break; * case Compression.L5RLE: * outFs.Write(Level5.Compress(openFile, 4)); * break;*/ case Compression.GZip: outFs.Write(GZip.Compress(openFile)); break; case Compression.Huff4: outFs.Write(Huffman.Compress(openFile, 4)); break; case Compression.Huff8: outFs.Write(Huffman.Compress(openFile, 8)); break; case Compression.LZ10: outFs.Write(LZ10.Compress(openFile)); break; case Compression.LZ11: outFs.Write(LZ11.Compress(openFile)); break; /*case Compression.LZSS: * outFs.Write(LZSS.Compress(openFile)); * break;*/ case Compression.RevLZ77: outFs.Write(RevLZ77.Compress(openFile)); break; case Compression.RLE: outFs.Write(RLE.Compress(openFile)); break; case Compression.ZLib: outFs.Write(ZLib.Compress(openFile)); break; } } catch (Exception ex) { MessageBox.Show(ex.ToString(), tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); } MessageBox.Show($"Successfully compressed {Path.GetFileName(openFile.Name)}.", tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Information); }
public static void WriteDeclaredSymbol(BinaryWriter writer, DeclaredSymbolInfo symbol, Huffman huffman) { Write7BitEncodedInt(writer, symbol.AssemblyNumber); writer.Write(symbol.Name); writer.Write(symbol.ID); WriteBytes(writer, huffman.Compress(symbol.Description)); Write7BitEncodedInt(writer, symbol.Glyph); }