Ejemplo n.º 1
0
        /* Appends the symbol statistics from the store. */
        static void GetStatistics(ZopfliLZ77Store store, SymbolStats stats)
        {
            ulong i;

            for (i = 0; i < store.size; i++)
            {
                if (store.dists[(int)i] == 0)
                {
                    stats.litlens[store.litlens[(int)i]]++;
                }
                else
                {
                    stats.litlens[Symbols.ZopfliGetLengthSymbol(store.litlens[(int)i])]++;
                    stats.dists[Symbols.ZopfliGetDistSymbol(store.dists[(int)i])]++;
                }
            }
            stats.litlens[256] = 1;  /* End symbol. */

            stats.CalculateStatistics();
        }
Ejemplo n.º 2
0
        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;
            }
        }