static void ZopfliCopyLZ77Store( ZopfliLZ77Store source, ZopfliLZ77Store dest) { dest.ResetStore(source.data); dest.litlens = new List <ushort>(source.litlens); dest.ll_counts = new List <ulong>(source.ll_counts); dest.d_counts = new List <ulong>(source.d_counts); dest.ll_symbol = new List <ushort>(source.ll_symbol); dest.d_symbol = new List <ushort>(source.d_symbol); dest.pos = new List <ulong>(source.pos); dest.dists = new List <ushort>(source.dists); dest.size = source.size; }
static void ZopfliLZ77Optimal(ZopfliBlockState s, byte[] InFile, int instart, int inend, int numiterations, ZopfliLZ77Store store) { /* Dist to get to here with smallest cost. */ int blocksize = inend - instart; ushort[] length_array = new ushort[blocksize + 1]; List <ushort> path = new List <ushort>(); ZopfliLZ77Store currentstore = new ZopfliLZ77Store(InFile); ZopfliHash h = new ZopfliHash(); SymbolStats stats = new SymbolStats(); SymbolStats beststats = new SymbolStats(); SymbolStats laststats = new SymbolStats(); int i; float[] costs = new float [blocksize + 1]; double cost; double bestcost = ZOPFLI_LARGE_FLOAT; double lastcost = 0; /* Try randomizing the costs a bit once the size stabilizes. */ RanState ran_state = new RanState(); int lastrandomstep = -1; /* Do regular deflate, then loop multiple shortest path runs, each time using * the statistics of the previous run. */ /* Initial run. */ ZopfliLZ77Greedy(s, InFile, instart, inend, currentstore, h); GetStatistics(currentstore, stats); /* Repeat statistics with each time the cost model from the previous stat * run. */ for (i = 0; i < numiterations; i++) { currentstore.ResetStore(InFile); LZ77OptimalRun(s, InFile, instart, inend, path, length_array, stats, currentstore, h, costs, false); cost = ZopfliCalculateBlockSize(currentstore, 0, currentstore.size, 2); if (Globals.verbose_more > 0 || (Globals.verbose > 0 && cost < bestcost)) { Console.WriteLine("Iteration " + i + ": " + cost + " bit"); } if (cost < bestcost) { /* Copy to the output store. */ ZopfliCopyLZ77Store(currentstore, store); CopyStats(stats, ref beststats); bestcost = cost; } CopyStats(stats, ref laststats); ClearStatFreqs(stats); GetStatistics(currentstore, stats); if (lastrandomstep != -1) { /* This makes it converge slower but better. Do it only once the * randomness kicks in so that if the user does few iterations, it gives a * better result sooner. */ AddWeighedStatFreqs(stats, 1.0, laststats, 0.5, stats); stats.CalculateStatistics(); } if (i > 5 && cost == lastcost) { CopyStats(beststats, ref stats); RandomizeStatFreqs(ran_state, stats); stats.CalculateStatistics(); lastrandomstep = i; } lastcost = cost; } }