Exemplo n.º 1
0
        static void ZopfliLZ77OptimalFixed(ZopfliBlockState s,
                                           byte[] InFile,
                                           ulong instart, ulong inend,
                                           ZopfliLZ77Store store)
        {
            /* Dist to get to here with smallest cost. */
            ulong blocksize = inend - instart;

            ushort[]      length_array = new ushort[blocksize + 1];
            List <ushort> path         = new List <ushort>();

            path.Add(0);
            ZopfliHash h = new ZopfliHash();

            float[]     costs = new float[blocksize + 1];
            SymbolStats stats = new SymbolStats();

            s.blockstart = (int)instart;
            s.blockend   = (int)inend;

            /* Shortest path for fixed tree This one should give the shortest possible
             * result for fixed tree, no repeated runs are needed since the tree is known. */
            LZ77OptimalRun(s, InFile, (int)instart, (int)inend, path,
                           length_array, stats, store, h, costs, true);
        }
Exemplo n.º 2
0
 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;
 }
Exemplo n.º 3
0
        /*
         * Does a single run for ZopfliLZ77Optimal. For good compression, repeated runs
         * with updated statistics should be performed.
         * s: the block state
         * in: the input data array
         * instart: where to start
         * inend: where to stop (not inclusive)
         * path: pointer to dynamically allocated memory to store the path
         * pathsize: pointer to the size of the dynamic path array
         * length_array: array of size (inend - instart) used to store lengths
         * costmodel: function to use as the cost model for this squeeze run
         * costcontext: abstract context for the costmodel function
         * store: place to output the LZ77 data
         * returns the cost that was, according to the costmodel, needed to get to the end.
         *  This is not the actual cost.
         */
        static double LZ77OptimalRun(ZopfliBlockState s,
                                     byte[] InFile, int instart, int inend, List <ushort> path,
                                     ushort[] length_array, SymbolStats stats, ZopfliLZ77Store store,
                                     ZopfliHash h, float[] costs, bool fixedcosts)
        {
            double cost     = GetBestLengths(s, InFile, instart, inend, stats, length_array, h, costs, fixedcosts);
            ulong  pathsize = 0;

            path.Clear();
            TraceBackwards((ulong)(inend - instart), length_array, path, ref pathsize);
            FollowPath(s, InFile, instart, inend, path, pathsize, store, h);
            Debug.Assert(cost < ZOPFLI_LARGE_FLOAT);
            return(cost);
        }
Exemplo n.º 4
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();
        }
Exemplo n.º 5
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;
            }
        }
Exemplo n.º 6
0
        static void FollowPath(ZopfliBlockState s,
                               byte[] InFile, int instart, int inend,
                               List <ushort> path, ulong pathsize,
                               ZopfliLZ77Store store, ZopfliHash h)
        {
            int i, j, pos;
            int windowstart = instart > ZopfliHash.ZOPFLI_WINDOW_SIZE
                ? instart - ZopfliHash.ZOPFLI_WINDOW_SIZE : 0;

            ulong total_length_test = 0;

            if (instart == inend)
            {
                return;
            }

            h.ZopfliResetHash();
            h.ZopfliWarmupHash(InFile, windowstart, inend);
            for (i = windowstart; i < instart; i++)
            {
                h.ZopfliUpdateHash(InFile, i, inend);
            }

            pos = instart;
            for (i = 0; i < (int)pathsize; i++)
            {
                ushort length       = path[i];
                ushort dummy_length = 0;
                ushort dist         = 0;
                Debug.Assert(pos < inend);

                h.ZopfliUpdateHash(InFile, pos, inend);

                /* Add to output. */
                if (length >= ZOPFLI_MIN_MATCH)
                {
                    /* Get the distance by recalculating longest match. The found length
                     * should match the length from the path. */
                    ZopfliFindLongestMatch(s, h, InFile, pos, inend, length, null,
                                           ref dist, ref dummy_length);
                    Debug.Assert(!(dummy_length != length && length > 2 && dummy_length > 2));
                    ZopfliVerifyLenDist(InFile, inend, pos, dist, length);
                    ZopfliStoreLitLenDist(length, dist, pos, store);
                    total_length_test += length;
                }
                else
                {
                    length = 1;
                    ZopfliStoreLitLenDist(InFile[pos], 0, pos, store);
                    total_length_test++;
                }


                Debug.Assert(pos + length <= inend);
                for (j = 1; j < length; j++)
                {
                    h.ZopfliUpdateHash(InFile, pos + j, inend);
                }

                pos += length;
            }
        }