Пример #1
0
        public override void Encode(IntField image, Stream output)
        {
            // Predictive transform
            image.ArgbTo4c();
            image.PredictionEnTransformXor(Seer);

            int          px = 0, py = 0;
            List <int>   dxs   = new List <int>();
            List <int>   dys   = new List <int>();
            List <int>   clr   = new List <int>();
            List <Point> jumps = new List <Point>();

            IntField vis     = new IntField(image.Width, image.Height);
            int      vis_ctr = 0;

            while (true)
            {
                Point pt = FindNextPixel(image, px, py);
                px += pt.X;
                py += pt.Y;
                int c = image.GetWrapped(px, py);
                if (c == 0)
                {
                    break;
                }
                if (Math.Abs(pt.X) > 5 || Math.Abs(pt.Y) > 5)
                {
                    jumps.Add(pt);
                }
                else
                {
                    dxs.Add(pt.X);
                    dys.Add(pt.Y);
                }
                clr.Add(c);
                image.SetWrapped(px, py, 0);
                if (vis_ctr % 1000 == 0)
                {
                    AddImageGrayscale(image, "progress.{0:00000}".Fmt(vis_ctr));
                }
                vis.SetWrapped(px, py, ++vis_ctr);
            }

            SetCounter("jumps", jumps.Count);

            AddIntDump("xs", dxs);
            AddIntDump("ys", dys);
            AddIntDump("cs", clr);

            AddImageGrayscale(vis, "seq-global");
            vis.Data = vis.Data.Select(val => val % 512).ToArray();
            AddImageGrayscale(vis, "seq-local");

            var xs = CodecUtil.InterleaveNegatives(dxs.ToArray());
            var ys = CodecUtil.InterleaveNegatives(dxs.ToArray());
            var cs = clr.ToArray();

            List <ulong[]> xps  = new List <ulong[]>();
            List <ulong[]> yps  = new List <ulong[]>();
            List <ulong>   xpts = new List <ulong>();
            List <ulong>   ypts = new List <ulong>();

            for (int given = 0; given <= 10; given++)
            {
                if (given < 10)
                {
                    xps.Add(CodecUtil.GetNextProbsGiven(xs, given));
                    yps.Add(CodecUtil.GetNextProbsGiven(ys, given));
                }
                else
                {
                    xps.Add(CodecUtil.GetNextProbsGivenGreater(xs, given - 1));
                    yps.Add(CodecUtil.GetNextProbsGivenGreater(ys, given - 1));
                }
                AddIntDump("xp-{0}".Fmt(given), xps.Last().Select(var => (int)var));
                AddIntDump("yp-{0}".Fmt(given), yps.Last().Select(var => (int)var));
                xpts.Add(xps.Last().Aggregate((tot, val) => tot + val));
                ypts.Add(yps.Last().Aggregate((tot, val) => tot + val));
            }

            List <ulong[]> cps = new List <ulong[]>();

            cps.Add(new ulong[4] {
                0, 1, 1, 1
            });
            for (int given = 1; given <= 3; given++)
            {
                cps.Add(CodecUtil.GetNextProbsGiven(cs, given));
                AddIntDump("cp-{0}".Fmt(given), cps.Last().Select(var => (int)var));
            }
            ulong[] cpts = new ulong[4];
            for (int i = 0; i < cps.Count; i++)
            {
                cpts[i] = cps[i].Aggregate((tot, val) => tot + val);
            }

            ArithmeticWriter aw = new ArithmeticWriter(output, null);
            int prev;

            //prev = 0;
            //for (int i = 0; i < cs.Length; i++)
            //{
            //    aw.Probs = cps[prev];
            //    aw.TotalProb = cpts[prev];
            //    aw.WriteSymbol(cs[i]);
            //    prev = cs[i];
            //}
            //aw.Flush();

            // For comparison: normal arithmetic 5846, shifting probs 3270
            //ulong[] probs = CodecUtil.CountValues(cs);
            //AddIntDump("cp-overall", probs.Select(val => (int)val));
            //ArithmeticWriter aw = new ArithmeticWriter(output, probs);
            //for (int i = 0; i < cs.Length; i++)
            //    aw.WriteSymbol(cs[i]);
            //aw.Flush();

            prev = 0;
            for (int i = 0; i < xs.Length; i++)
            {
                if (prev > 10)
                {
                    prev = 10;
                }
                aw.Probs     = xps[prev];
                aw.TotalProb = xpts[prev];
                aw.WriteSymbol(xs[i]);
                prev = xs[i];
            }
            aw.Flush();

            //prev = 0;
            //for (int i = 0; i < ys.Length; i++)
            //{
            //    if (prev > 10) prev = 10;
            //    aw.Probs = yps[prev];
            //    aw.TotalProb = ypts[prev];
            //    aw.WriteSymbol(ys[i]);
            //    prev = ys[i];
            //}
            //aw.Flush();
        }