コード例 #1
0
        public override void Encode(IntField image, Stream output)
        {
            image.ArgbTo4c();
            IntField orig = image.Clone();
            //image.PredictionEnTransformXor(new HorzVertForeseer());
            //IntField backgr = CodecUtil.BackgroundFilterThin(image, 2, 2);
            IntField backgr = CodecUtil.BackgroundFilterSmall(image, 50);

            AddImageGrayscale(image, "orig");
            AddImageGrayscale(backgr, "backgr");

            for (int p = 0; p < image.Data.Length; p++)
            {
                image.Data[p] ^= backgr.Data[p];
            }

            AddImageGrayscale(image, "foregr");


            for (int i = 1; i <= 3; i++)
            {
                IntField field = image.Clone();
                field.Conditional(pix => pix == i);
                int[] syms = CodecUtil.LzwLinesEn(field, 4, 1);
                AddImageGrayscale(field, "field{0}-{1}syms-max{2}".Fmt(i, syms.Length, syms.Max()));
            }
        }
コード例 #2
0
ファイル: Compressor.cs プロジェクト: rstarkov/i4c
        public void AddImageGrayscale(IntField image, int min, int max, string caption)
        {
            IntField temp = image.Clone();

            temp.ArgbFromField(min, max);
            Images.Add(new Tuple <string, IntField>(caption, temp));
        }
コード例 #3
0
        public static int[] FieldcodeRunlengthsEn2(IntField image, SymbolCodec runlengthCodec, Compressor compr)
        {
            compr.AddImageGrayscale(image, 0, 3, "xformed");
            List <int> data = new List <int>();

            for (int i = 1; i <= 3; i++)
            {
                IntField temp = image.Clone();
                temp.Map(x => x == i ? 1 : 0);
                data.AddRange(temp.Data);
                compr.AddImageGrayscale(temp, 0, 1, "field" + i);
            }
            var runs = runlengthCodec.Encode(data.ToArray());

            compr.SetCounter("runs", runs.Length);
            return(runs);
        }
コード例 #4
0
        public static List <int[]> FieldcodeRunlengthsEn(IntField image, SymbolCodec runlengthCodec, Compressor compr)
        {
            compr.AddImageGrayscale(image, 0, 3, "xformed");
            var fields = new List <int[]>();

            for (int i = 1; i <= 3; i++)
            {
                IntField temp = image.Clone();
                temp.Map(x => x == i ? 1 : 0);
                var field = runlengthCodec.Encode(temp.Data);
                CodecUtil.Shift(field, 1);
                compr.SetCounter("symbols|field-" + i, field.Length);
                fields.Add(field);
                compr.AddImageGrayscale(temp, 0, 1, "field" + i);
            }
            return(fields);
        }
コード例 #5
0
        public override void Encode(IntField image, Stream output)
        {
            // Predictive transform
            image.ArgbTo4c();
            image.PredictionEnTransformXor(Seer);

            // Convert to three fields' runlengths
            for (int i = 1; i <= 3; i++)
            {
                IntField temp = image.Clone();
                temp.Map(x => x == i ? 1 : 0);
                AddImageGrayscale(temp, 0, 1, "field" + i);
                var runs = new RunLength01SplitCodec().EncodeSplit(temp.Data);
                SetCounter("runs|field{0}|0s".Fmt(i), runs.Item1.Count);
                SetCounter("runs|field{0}|1s".Fmt(i), runs.Item2.Count);
                AddIntDump("field{0}-0s".Fmt(i), runs.Item1);
                AddIntDump("field{0}-1s".Fmt(i), runs.Item2);
            }
        }
コード例 #6
0
        public static IntField BackgroundFilterSmall(IntField image, int areaThresh)
        {
            image = image.Clone();
            IntField processed = image.Clone();

            // 0..3 - original unprocessed colors
            // -1   - accepted as background
            // -2   - trial fill / kept for later elimination
            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    if (processed[x, y] >= 0)
                    {
                        // Do trial fill
                        processed.Floodfill(x, y, -2);
                        // Accept as background?
                        if (processed.Counter_Floodfill_TotalPixels > areaThresh)
                        {
                            processed.Floodfill(x, y, -1);
                        }
                    }
                }
            }

            for (int p = 0; p < image.Data.Length; p++)
            {
                if (processed.Data[p] == -2)
                {
                    image.Data[p] = -2;
                }
            }

            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    if (processed[x, y] == -2)
                    {
                        if (x > 0 && processed[x - 1, y] == -1)
                        {
                            image.Floodfill(x, y, image[x - 1, y]);
                            processed.Floodfill(x, y, -3);
                        }
                        else if (y > 0 && processed[x, y - 1] == -1)
                        {
                            image.Floodfill(x, y, image[x, y - 1]);
                            processed.Floodfill(x, y, -3);
                        }
                        else if (x < image.Width - 1 && processed[x + 1, y] == -1)
                        {
                            image.Floodfill(x, y, image[x + 1, y]);
                            processed.Floodfill(x, y, -3);
                        }
                        else if (y < image.Height - 1 && processed[x, y + 1] == -1)
                        {
                            image.Floodfill(x, y, image[x, y + 1]);
                            processed.Floodfill(x, y, -3);
                        }
                    }
                }
            }

            return(image);
        }
コード例 #7
0
        public static IntField BackgroundFilterThin(IntField image, int w1passes, int w2passes)
        {
            image = image.Clone();

            bool changed = true;
            int  counter = 0;

            while (changed)
            {
                changed = false;
                for (int y = 0; y < image.Height; y++)
                {
                    for (int x = 1; x < image.Width - 1; x++)
                    {
                        if (image[x - 1, y] == image[x + 1, y] && image[x, y] != image[x - 1, y])
                        {
                            image[x, y] = image[x - 1, y];
                            changed     = true;
                        }
                    }
                }

                for (int x = 0; x < image.Width; x++)
                {
                    for (int y = 1; y < image.Height - 1; y++)
                    {
                        if (image[x, y - 1] == image[x, y + 1] && image[x, y] != image[x, y - 1])
                        {
                            image[x, y] = image[x, y - 1];
                            changed     = true;
                        }
                    }
                }

                counter++;
                if (counter >= w1passes)
                {
                    break;
                }
            }

            changed = true;
            counter = 0;
            while (changed)
            {
                changed = false;
                for (int y = 0; y < image.Height; y++)
                {
                    for (int x = 2; x < image.Width - 1; x++)
                    {
                        if (image[x - 2, y] == image[x + 1, y] && image[x, y] != image[x - 2, y])
                        {
                            image[x, y] = image[x - 2, y];
                            changed     = true;
                        }
                        if (image[x - 2, y] == image[x + 1, y] && image[x - 1, y] != image[x - 2, y])
                        {
                            image[x - 1, y] = image[x - 2, y];
                            changed         = true;
                        }
                    }
                }

                for (int x = 0; x < image.Width; x++)
                {
                    for (int y = 2; y < image.Height - 1; y++)
                    {
                        if (image[x, y - 2] == image[x, y + 1] && image[x, y - 1] != image[x, y - 2])
                        {
                            image[x, y - 1] = image[x, y - 2];
                            changed         = true;
                        }
                    }
                }

                counter++;
                if (counter >= w2passes)
                {
                    break;
                }
            }

            return(image);
        }
コード例 #8
0
ファイル: I4cEcho.cs プロジェクト: rstarkov/i4c
        private void saveColors(IntField foregr)
        {
            var clr = foregr.Data.Where(pix => pix > 0).ToArray();

            Tuple <int, int>[] cc = new Tuple <int, int> [3];
            cc[0] = new Tuple <int, int>(clr.Where(pix => pix == 1).Count(), 1);
            cc[1] = new Tuple <int, int>(clr.Where(pix => pix == 2).Count(), 2);
            cc[2] = new Tuple <int, int>(clr.Where(pix => pix == 3).Count(), 3);
            cc    = cc.OrderBy(tup => - tup.Item1).ToArray();
            int      c1    = cc[0].Item2;
            int      c2    = cc[1].Item2;
            int      c3    = cc[2].Item2;
            IntField cover = foregr.Clone();

            cover.Map(pix => pix == c1 ? 1 : pix == c2 ? 5 : 0);
            AddImageGrayscale(cover, 0, 5, "25-cover-2s");
            cover = foregr.Clone();
            cover.Map(pix => pix == c1 ? 1 : pix == c2 ? 1 : pix == c3 ? 5 : 0);
            AddImageGrayscale(cover, 0, 5, "26-cover-3s");
            AddIntDump("colors", clr);

            List <int>[] runs = new List <int> [4];
            runs[1] = new List <int>();
            runs[2] = new List <int>();
            runs[3] = new List <int>();
            int p = 0;

            while (p < clr.Length)
            {
                for (int c = 1; c <= 3; c++)
                {
                    int pbefore = p;
                    while (p < clr.Length && clr[p] == c)
                    {
                        p++;
                    }
                    runs[c].Add(p - pbefore);
                }
            }
            runs[1].Add(0);
            runs[2].Add(0);
            runs[3].Add(0);
            AddIntDump("color-runs-1", runs[1]);
            AddIntDump("color-runs-2", runs[2]);
            AddIntDump("color-runs-3", runs[3]);

            List <int>[] leftovers = new List <int> [4];
            leftovers[1] = mrleCutOff(runs[1], 31);
            leftovers[2] = mrleCutOff(runs[2], 31);
            leftovers[3] = mrleCutOff(runs[3], 31);

            ulong[][] probs1 = mrleGetProbs(runs[1].ToArray(), 31);
            ulong[][] probs2 = mrleGetProbs(runs[2].ToArray(), 31);
            ulong[][] probs3 = mrleGetProbs(runs[3].ToArray(), 31);

            SetCounter("bytes|colors|probs", -1);

            SetCounter("bytes|colors|shortruns|1", mrleEncodeShort(runs[1].ToArray(), probs1).Length);
            SetCounter("bytes|colors|shortruns|2", mrleEncodeShort(runs[2].ToArray(), probs2).Length);
            SetCounter("bytes|colors|shortruns|3", mrleEncodeShort(runs[3].ToArray(), probs3).Length);

            SetCounter("bytes|colors|longruns|1", mrleEncodeLong(leftovers[1].ToArray()).Length);
            SetCounter("bytes|colors|longruns|2", mrleEncodeLong(leftovers[2].ToArray()).Length);
            SetCounter("bytes|colors|longruns|3", mrleEncodeLong(leftovers[3].ToArray()).Length);
        }
コード例 #9
0
ファイル: I4cEcho.cs プロジェクト: rstarkov/i4c
        private void backgroundSplit(IntField image, out IntField backgr, out IntField foregr)
        {
            IntField largeBackgrMap;

            // First pass: all large areas are always backgrounds
            {
                IntField vis_hitpoints = image.Clone();
                largeBackgrMap = image.Clone();
                int    x = 0, y = 0, xfr = 0;
                double yd      = 0;
                double ystep   = _backgrLargeStepSize * 0.866 / ((double)image.Width / _backgrLargeStepSize);
                int    curfill = -2;
                while (true)
                {
                    y = (int)yd;
                    if (y >= image.Height)
                    {
                        break;
                    }

                    vis_hitpoints[x, y] = 10;
                    if (largeBackgrMap[x, y] >= 0)
                    {
                        largeBackgrMap.Floodfill(x, y, curfill);
                        curfill--;
                        if (largeBackgrMap.Counter_Floodfill_TotalPixels > _backgrLargeAreaThresh)
                        {
                            largeBackgrMap.Floodfill(x, y, -1);
                        }
                    }

                    yd += ystep;
                    x  += _backgrLargeStepSize;
                    if (x >= image.Width)
                    {
                        xfr += _backgrLargeStepSize / 3;
                        if (xfr > _backgrLargeStepSize)
                        {
                            xfr -= _backgrLargeStepSize;
                        }
                        x = xfr;
                    }
                }

                largeBackgrMap.Map(pix => pix == -1 ? 1 : 0);
                AddImageGrayscale(vis_hitpoints, "10-bkg-large-hitpoints");
                AddImageGrayscale(largeBackgrMap, "11-bkg-large-map");
            }

            // TODO: also background if perfectly rectangular and larger than 4 area

            // Second pass - background continuation
            {
                // Prepare image
                backgr = image.Clone();
                for (int p = 0; p < image.Data.Length; p++)
                {
                    if (largeBackgrMap.Data[p] == 0)
                    {
                        backgr.Data[p] = -1;
                    }
                }
                AddImageGrayscale(backgr, -1, 3, "12-bkg-cont-before");

                // Horizontal continuation
                for (int y = 0; y < backgr.Height; y++)
                {
                    int lastbg      = -1;
                    int lastfgstart = -1;  // -1 means not in a foreground run
                    int x           = 0;
                    while (true)
                    {
                        if (lastfgstart != -1 && (x == backgr.Width || backgr[x, y] != -1))
                        {   // in a fg run and either end of image or end of run (no longer foreground)
                            if (lastbg == -1 || x == backgr.Width || lastbg == backgr[x, y])
                            {
                                int clr = x == backgr.Width ? lastbg : backgr[x, y];
                                for (int fx = lastfgstart; fx < x; fx++)
                                {
                                    backgr[fx, y] = clr;
                                }
                            }
                            lastfgstart = -1;
                        }
                        if (x == backgr.Width)
                        {
                            break;
                        }
                        if (lastfgstart == -1 && backgr[x, y] == -1)
                        {
                            lastfgstart = x;
                            lastbg      = x == 0 ? -1 : backgr[x - 1, y];
                        }
                        x++;
                    }
                }
                AddImageGrayscale(backgr, -1, 3, "13-bkg-cont-horz");

                // Vertical continuation
                for (int x = 0; x < backgr.Width; x++)
                {
                    int lastbg      = -1;
                    int lastfgstart = -1;  // -1 means not in a foreground run
                    int y           = 0;
                    while (true)
                    {
                        if (lastfgstart != -1 && (y == backgr.Height || backgr[x, y] != -1))
                        {   // in a fg run and either end of image or end of run (no longer foreground)
                            if (lastbg == -1 || y == backgr.Height || lastbg == backgr[x, y])
                            {
                                int clr = y == backgr.Height ? lastbg : backgr[x, y];
                                for (int fy = lastfgstart; fy < y; fy++)
                                {
                                    backgr[x, fy] = clr;
                                }
                            }
                            lastfgstart = -1;
                        }
                        if (y == backgr.Height)
                        {
                            break;
                        }
                        if (lastfgstart == -1 && backgr[x, y] == -1)
                        {
                            lastfgstart = y;
                            lastbg      = y == 0 ? -1 : backgr[x, y - 1];
                        }
                        y++;
                    }
                }
                AddImageGrayscale(backgr, -1, 3, "14-bkg-cont-vert");

                // Continuation of leftover areas
                int lastc = -1;
                for (int p = 0; p < backgr.Data.Length; p++)
                {
                    if (backgr.Data[p] == -1 && lastc != -1)
                    {
                        backgr.Floodfill(p % backgr.Width, p / backgr.Width, lastc);
                    }
                    else if (p > 0 && backgr.Data[p - 1] == -1 && backgr.Data[p] != -1)
                    {
                        backgr.Floodfill((p - 1) % backgr.Width, (p - 1) / backgr.Width, backgr.Data[p]);
                    }
                    if (backgr.Data[p] != -1)
                    {
                        lastc = backgr.Data[p];
                    }
                }

                // TODO: remove anything that's highly non-rect

                AddImageGrayscale(backgr, 0, 3, "15-final-bkg");
            }

            // Final pass - extract foreground
            {
                foregr = image.Clone();
                for (int p = 0; p < image.Data.Length; p++)
                {
                    foregr.Data[p] ^= backgr.Data[p];
                }
                AddImageGrayscale(foregr, 0, 3, "16-final-fgr");
            }
        }
コード例 #10
0
ファイル: XperimentRects.cs プロジェクト: rstarkov/i4c
        public override void Encode(IntField image, Stream output)
        {
            image.ArgbTo4c();
            image.PredictionEnTransformXor(Seer);
            IntField[]         fields  = new IntField[4];
            IntField[]         cutmaps = new IntField[4];
            List <Rectangle>[] areases = new List <Rectangle> [4];
            for (int i = 1; i <= 3; i++)
            {
                fields[i] = image.Clone();
                fields[i].Map(x => x == i ? 1 : 0);
                cutmaps[i] = fields[i].ReduceKeepingPixels(ReduceBlocksize);

                areases[i] = new List <Rectangle>();
                IntField remains = fields[i].Clone();
                while (true)
                {
                    List <Rectangle> rects = CodecUtil.FindAllRects(cutmaps[i]);
                    if (rects.Count == 0 || rects[0].Width * rects[0].Height <= 1)
                    {
                        break;
                    }

                    Rectangle r = new Rectangle(rects[0].Left * ReduceBlocksize, rects[0].Top * ReduceBlocksize,
                                                rects[0].Width * ReduceBlocksize, rects[0].Height * ReduceBlocksize);
                    r = CodecUtil.ShrinkRectangle(remains, r);
                    areases[i].Add(r);

                    cutmaps[i].ShadeRect(rects[0].Left, rects[0].Top, rects[0].Width, rects[0].Height, 0, 0);
                    remains.ShadeRect(r.Left, r.Top, r.Width, r.Height, 0, 0);
                }

                SetCounter("areas|" + i, areases[i].Count);

                IntField vis = fields[i].Clone();
                vis.ArgbFromField(0, 1);
                foreach (var area in areases[i])
                {
                    vis.ShadeRect(area.Left, area.Top, area.Width, area.Height, 0xFFFF7F7F, 0x007F0000);
                }
                for (int x = 0; x < cutmaps[i].Width; x++)
                {
                    for (int y = 0; y < cutmaps[i].Height; y++)
                    {
                        if (cutmaps[i][x, y] > 0)
                        {
                            vis.ShadeRect(x * ReduceBlocksize, y * ReduceBlocksize, ReduceBlocksize, ReduceBlocksize,
                                          0xFF7FFF7F, 0x00007F00);
                        }
                    }
                }
                AddImageArgb(vis, "vis" + i);
            }

            // now have: fields, covered in part by areas and in part by cutmap (only remaining cutmap left at this stage)

            long pos = 0;

            output.WriteInt32Optim(image.Width);
            output.WriteInt32Optim(image.Height);
            SetCounter("bytes|size", output.Position - pos);
            pos = output.Position;

            for (int i = 1; i <= 3; i++)
            {
                output.WriteInt32Optim(areases[i].Count);
            }
            SetCounter("bytes|areas|count", output.Position - pos);
            pos = output.Position;

            for (int i = 1; i <= 3; i++)
            {
                foreach (var area in areases[i])
                {
                    output.WriteInt32Optim(area.Left);
                    output.WriteInt32Optim(area.Top);
                }
                SetCounter("bytes|areas|x,y|" + i, output.Position - pos);
                pos = output.Position;
            }

            for (int i = 1; i <= 3; i++)
            {
                foreach (var area in areases[i])
                {
                    output.WriteInt32Optim(area.Width);
                    output.WriteInt32Optim(area.Height);
                }
                SetCounter("bytes|areas|w,h|" + i, output.Position - pos);
                pos = output.Position;
            }

            for (int i = 1; i <= 3; i++)
            {
                var pts = CodecUtil.GetPixelCoords(cutmaps[i], 1);
                SetCounter("leftpixels|" + i, pts.Count);
                output.WriteInt32Optim(pts.Count);
                foreach (var pt in pts)
                {
                    output.WriteInt32Optim(pt.X);
                    output.WriteInt32Optim(pt.Y);
                }
            }

            RunLength01MaxSmartCodec runlen = new RunLength01MaxSmartCodec(FieldcodeSymbols);
            List <int> data    = new List <int>();
            List <int> visdata = new List <int>();

            for (int i = 1; i <= 3; i++)
            {
                foreach (var area in areases[i])
                {
                    int[] aredata = fields[i].GetRectData(area);
                    data.AddRange(aredata);
                    visdata.AddRange(aredata.Select(val => unchecked ((int)0xFF000000) | ((i == 1 ? 0xF00000 : i == 2 ? 0xF08000 : 0xF00080) >> (2 - val * 2))));
                    fields[i].ShadeRect(area.Left, area.Top, area.Width, area.Height, 0, 0);
                }
            }
            for (int i = 1; i <= 3; i++)
            {
                var pts = CodecUtil.GetPixelCoords(cutmaps[i], 1);
                foreach (var pt in pts)
                {
                    Rectangle rect    = new Rectangle(pt.X * ReduceBlocksize, pt.Y * ReduceBlocksize, ReduceBlocksize, ReduceBlocksize);
                    int[]     aredata = fields[i].GetRectData(rect);
                    data.AddRange(aredata);
                    visdata.AddRange(aredata.Select(val => unchecked ((int)0xFF000000) | ((i == 1 ? 0x00F000 : i == 2 ? 0x80F000 : 0x00F080) >> (2 - val * 2))));
                }
            }
            int[] dataA   = data.ToArray();
            int[] symbols = runlen.Encode(dataA);
            SetCounter("crux-pixels", data.Count);
            SetCounter("crux-rle-symbols", symbols.Length);

            int      viw    = (int)(Math.Sqrt(data.Count) * 1.3);
            int      vih    = (int)Math.Ceiling((double)data.Count / viw);
            IntField visual = new IntField(viw, vih);

            Array.Copy(visdata.ToArray(), visual.Data, visdata.Count);
            AddImageArgb(visual, "crux");

            var probs = CodecUtil.CountValues(symbols);

            output.WriteUInt32Optim((uint)probs.Length);
            for (int p = 0; p < probs.Length; p++)
            {
                output.WriteUInt64Optim(probs[p]);
            }
            SetCounter("bytes|probs", output.Position - pos);
            pos = output.Position;

            ArithmeticWriter aw = new ArithmeticWriter(output, probs);

            foreach (int sym in symbols)
            {
                aw.WriteSymbol(sym);
            }
            SetCounter("bytes|crux", output.Position - pos);
            pos = output.Position;
            aw.Flush();

            // BETTER RLE - RUNS OF 1'S
            // ARITH THE AREAS
            // ARITH THE PROBS
            // SHRINK GREENS
        }
コード例 #11
0
ファイル: Compressor.cs プロジェクト: rstarkov/i4c
 public void AddImageArgb(IntField image, string caption)
 {
     Images.Add(new Tuple <string, IntField>(caption, image.Clone()));
 }