Пример #1
0
        public override int Foresee(IntField image, int x, int y)
        {
            int l  = x == 0 ? 0 : image[x - 1, y];
            int t  = y == 0 ? 0 : image[x, y - 1];
            int tl = (x == 0 || y == 0) ? 0 : image[x - 1, y - 1];

            if (l == tl && t == tl)
            {
                return(tl); // solid fill
            }
            else if (l == tl)
            {
                return(t);  // vertical line
            }
            else if (t == tl)
            {
                return(l);  // horizontal line
            }
            else if (t == l)
            {
                return(tl); // 50% diffusion fill
            }
            else
            {
                return(tl);  // favour diagonals from top-left to bottom-right
            }
        }
Пример #2
0
        public static int MostFrequent(IntField image, int ptX, int ptY, int lookbackW, int lookbackH)
        {
            Dictionary <int, int> counts = new Dictionary <int, int>();

            for (int y = ptY - lookbackH + 1; y <= ptY; y++)
            {
                for (int x = ptX - lookbackW + 1; x <= ptX; x++)
                {
                    if (y != ptY && x != ptX && y >= 0 && x >= 0)
                    {
                        int sym = image[x, y];
                        if (counts.ContainsKey(sym))
                        {
                            counts[sym]++;
                        }
                        else
                        {
                            counts.Add(sym, 1);
                        }
                    }
                }
            }
            if (counts.Count == 0)
            {
                return(0);
            }
            int maxcount = counts.Values.Max();

            return(counts.Where(kvp => kvp.Value == maxcount).First().Key);
        }
Пример #3
0
        public override int Foresee(IntField image, int x, int y)
        {
            pattern horzProbe = findPattern(image, x - _horzLookback, y - _horzThickness + 1, _horzLookback, _horzThickness);
            pattern vertProbe = findPattern(image, x - _vertThickness + 1, y - _vertLookback, _vertThickness, _vertLookback);

            if (horzProbe == pattern.Dirty && vertProbe == pattern.Dirty)
            {
                return(MostFrequentForeseer.MostFrequent(image, x, y, _freqThickness, _freqThickness));
            }

            bool haveH = horzProbe == pattern.CleanHorz || vertProbe == pattern.CleanHorz;
            bool haveV = horzProbe == pattern.CleanVert || vertProbe == pattern.CleanVert;

            if (haveH && !haveV)
            {
                return(MostFrequentForeseer.MostFrequent(image, x, y, _horzLookback, _horzThickness));
            }
            if (haveV && !haveH)
            {
                return(MostFrequentForeseer.MostFrequent(image, x, y, _vertThickness, _vertLookback));
            }

            if (horzProbe == pattern.Solid)
            {
                return(MostFrequentForeseer.MostFrequent(image, x, y, _horzLookback, _horzThickness));
            }
            else
            {
                return(MostFrequentForeseer.MostFrequent(image, x, y, _vertThickness, _vertLookback));
            }
        }
Пример #4
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()));
            }
        }
Пример #5
0
        public static int[] LzwLinesEn(IntField bitfield, int lineheight, int backadd)
        {
            int[]    symbols = BitImageToLineSymbols(bitfield, lineheight);
            LzwCodec lzw     = new LzwCodec(1 << lineheight);

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

            // Convert to three fields' runlengths
            var fields = CodecUtil.FieldcodeRunlengthsEn(image, new RunLength01MaxSmartCodec(FieldcodeSymbols), this);

            // Write size
            DeltaTracker pos = new DeltaTracker();

            output.WriteUInt32Optim((uint)image.Width);
            output.WriteUInt32Optim((uint)image.Height);
            SetCounter("bytes|size", pos.Next(output.Position));

            // Write probs
            ulong[] probs = CodecUtil.GetFreqsForAllSections(fields, FieldcodeSymbols + 1);
            probs[0] = 6;
            CodecUtil.SaveFreqsCrappy(output, probs);
            SetCounter("bytes|probs", pos.Next(output.Position));

            // Write fields
            ArithmeticSectionsCodec ac = new ArithmeticSectionsCodec(probs, 6, output);

            for (int i = 0; i < fields.Count; i++)
            {
                ac.WriteSection(fields[i]);
                SetCounter("bytes|fields|" + (i + 1), pos.Next(output.Position));
            }
            ac.Encode();
            SetCounter("bytes|arith-err", pos.Next(output.Position));
        }
Пример #7
0
        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));
        }
Пример #8
0
        public override void Encode(IntField image, Stream output)
        {
            // Predictive transform
            image.ArgbTo4c();
            image.PredictionEnTransformXor(Seer);

            // Convert to three fields' runlengths
            var fields = CodecUtil.FieldcodeRunlengthsEn2(image, RLE, this);

            SetCounter("rle|longer", (RLE as RunLength01LongShortCodec).Counter_Longers);
            SetCounter("rle|muchlonger", (RLE as RunLength01LongShortCodec).Counter_MuchLongers);

            // Write size
            DeltaTracker pos = new DeltaTracker();

            output.WriteUInt32Optim((uint)image.Width);
            output.WriteUInt32Optim((uint)image.Height);
            SetCounter("bytes|size", pos.Next(output.Position));

            // Write probs
            ulong[] probs = CodecUtil.CountValues(fields, RLE.MaxSymbol);
            CodecUtil.SaveFreqs(output, probs, TimwiCecCompressor.runLProbsProbs, "");
            SetCounter("bytes|probs", pos.Next(output.Position));

            // Write fields
            ArithmeticWriter aw = new ArithmeticWriter(output, probs);

            output.WriteUInt32Optim((uint)fields.Length);
            foreach (var sym in fields)
            {
                aw.WriteSymbol(sym);
            }
            aw.Flush();
            SetCounter("bytes|fields", pos.Next(output.Position));
        }
Пример #9
0
        public int PredictionEnTransformXor(Foreseer foreseer)
        {
            IntField orig = this.Clone();

            foreseer.Initialize(orig);
            int wrongPredictions = 0;

            int p = 0;

            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++, p++)
                {
                    int predicted = foreseer.Foresee(orig, x, y);
                    Data[p] = orig.Data[p] ^ predicted;
                    if (Data[p] != 0)
                    {
                        wrongPredictions++;
                    }
                    foreseer.Learn(orig, x, y, orig.Data[p], predicted);
                }
            }

            return(wrongPredictions);
        }
Пример #10
0
        public override IntField Decode(Stream input)
        {
            // Read size
            int w = (int)input.ReadUInt32Optim();
            int h = (int)input.ReadUInt32Optim();

            // Read probabilities
            ulong[] probs = CodecUtil.LoadFreqsCrappy(input, FieldcodeSymbols + 1);
            // Read fields
            ArithmeticSectionsCodec ac = new ArithmeticSectionsCodec(probs, 6);

            ac.Decode(input);
            var fields = new List <int[]>();

            for (int i = 1; i <= 3; i++)
            {
                fields.Add(ac.ReadSection());
            }

            // Undo fieldcode
            IntField transformed = CodecUtil.FieldcodeRunlengthsDe(fields, w, h, new RunLength01MaxSmartCodec(FieldcodeSymbols), this);

            // Undo predictive transform
            transformed.PredictionDeTransformXor(Seer);
            transformed.ArgbFromField(0, 3);
            return(transformed);
        }
Пример #11
0
        public static IntField FieldcodeRunlengthsDe(List <int[]> fields, int width, int height, SymbolCodec runlengthCodec, Compressor compr)
        {
            IntField image = new IntField(width, height);

            for (int i = 1; i <= 3; i++)
            {
                CodecUtil.Shift(fields[i - 1], -1);
                var f = runlengthCodec.Decode(fields[i - 1]);

                for (int p = 0; p < width * height; p++)
                {
                    if (f[p] == 1)
                    {
                        image.Data[p] = i;
                    }
                }

                // Visualise
                IntField img = new IntField(width, height);
                img.Data = f;
                compr.AddImageGrayscale(img, 0, 1, "field" + i);
            }
            compr.AddImageGrayscale(image, 0, 3, "xformed");
            return(image);
        }
Пример #12
0
        public override IntField Decode(Stream input)
        {
            // Read size
            int w = (int)input.ReadUInt32Optim();
            int h = (int)input.ReadUInt32Optim();

            // Read probabilities
            ulong[] probs = CodecUtil.LoadFreqs(input, TimwiCecCompressor.runLProbsProbs, RLE.MaxSymbol + 1);
            // Read fields
            int len = (int)input.ReadUInt32Optim();
            ArithmeticCodingReader acr = new ArithmeticCodingReader(input, probs);

            int[] fields = new int[len];
            for (int p = 0; p < len; p++)
            {
                fields[p] = acr.ReadSymbol();
            }

            // Undo fieldcode
            IntField transformed = CodecUtil.FieldcodeRunlengthsDe2(fields, w, h, RLE, this);

            // Undo predictive transform
            transformed.PredictionDeTransformXor(Seer);
            transformed.ArgbFromField(0, 3);
            return(transformed);
        }
Пример #13
0
        public IntField ReduceKeepingPixels(int blocksize)
        {
            IntField img = new IntField((Width + blocksize - 1) / blocksize, (Height + blocksize - 1) / blocksize);

            for (int y = 0; y < img.Height; y++)
            {
                for (int x = 0; x < img.Width; x++)
                {
                    int ix_end = Math.Min(x * blocksize + blocksize, Width);
                    int iy_end = Math.Min(y * blocksize + blocksize, Height);
                    for (int iy = y * blocksize; iy < iy_end; iy++)
                    {
                        for (int ix = x * blocksize; ix < ix_end; ix++)
                        {
                            if (this[ix, iy] != 0)
                            {
                                img[x, y] = 1;
                                goto breakout;
                            }
                        }
                    }
                    breakout :;
                }
            }
            return(img);
        }
Пример #14
0
 public override void Learn(IntField image, int x, int y, int actual, int predicted)
 {
     foreach (var size in _sizes)
     {
         ulong hash = HashImageRegion(image, x, y, size.Width, size.Height);
         _hashtable.AddCount(hash, actual);
     }
 }
Пример #15
0
        public IntField Clone()
        {
            IntField result = (IntField)MemberwiseClone();

            result.Data = new int[result.Data.Length];
            Array.Copy(Data, result.Data, Data.Length);
            return(result);
        }
Пример #16
0
        public IntField Extract(int fx, int fy, int width, int height)
        {
            IntField result = new IntField(width, height);

            for (int y = fy; y < fy + height; y++)
            {
                Array.Copy(Data, fx + y * Width, result.Data, (y - fy) * width, width);
            }
            return(result);
        }
Пример #17
0
        public static List <Point> GetPixelCoords(IntField image, int color)
        {
            var indices = image.Data.Select((pix, ntx) => pix == color ? ntx : -1).Where(val => val >= 0);
            var result  = new List <Point>();

            foreach (var index in indices)
            {
                result.Add(new Point(index % image.Width, index / image.Width));
            }
            return(result);
        }
Пример #18
0
        public static void AddImageTab(IntField argb, string caption)
        {
            if (TheInstance == null) // we're running in command line mode
            {
                return;
            }

            lock (Images)
            {
                Images.Enqueue(new Tuple <string, IntField>(caption, argb));
            }
        }
Пример #19
0
        public IntField HalfResNearestNeighbour()
        {
            IntField result = new IntField((Width + 1) / 2, (Height + 1) / 2);

            for (int x = 0; x < Width; x += 2)
            {
                for (int y = 0; y < Height; y += 2)
                {
                    result[x >> 1, y >> 1] = this[x, y];
                }
            }
            return(result);
        }
Пример #20
0
        /// <summary>
        /// Decompresses a single file using a given compressor, saving all debug or
        /// visualisation outputs to the specified directory.
        /// </summary>
        public static void DecompressFile(Compressor compr, string sourcePath, string destDir, string destFile)
        {
            FileStream input = File.Open(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            IntField   f     = compr.Decode(input);

            input.Close();

            Directory.CreateDirectory(destDir);
            f.ArgbToBitmap().Save(Path.Combine(destDir, destFile), ImageFormat.Png);
            SaveComprImages(compr, destDir);
            SaveComprDumps(compr, destDir);
            SaveComprCounters(compr, destDir);
        }
Пример #21
0
        public IntField HalfResHighestCount()
        {
            IntField result = new IntField((Width + 1) / 2, (Height + 1) / 2);

            for (int x = 0; x < Width; x += 2)
            {
                for (int y = 0; y < Height; y += 2)
                {
                    result[x >> 1, y >> 1] = MostFrequent(this[x, y], this[x + 1, y], this[x, y + 1], this[x + 1, y + 1]);
                }
            }
            return(result);
        }
Пример #22
0
        private pattern findPattern(IntField image, int fx, int fy, int tw, int th)
        {
            int c = image[fx, fy];
            int h = image[fx + 1, fy];
            int v = image[fx, fy + 1];

            bool certainlyNotCH    = c != h;
            bool certainlyNotCV    = c != v;
            bool certainlyNotSolid = c != h || c != v;

            for (int y = fy + 1; y < fy + th; y++)
            {
                for (int x = fx + 1; x < fx + tw; x++)
                {
                    c = image[x, y];
                    h = image[x - 1, y];
                    v = image[x, y - 1];

                    if (!certainlyNotSolid && (c != h || c != v))
                    {
                        certainlyNotSolid = true;
                    }
                    if (!certainlyNotCH && (c != h))
                    {
                        certainlyNotCH = true;
                    }
                    if (!certainlyNotCV && (c != v))
                    {
                        certainlyNotCV = true;
                    }

                    if (certainlyNotCH && certainlyNotCV && certainlyNotSolid)
                    {
                        return(pattern.Dirty);
                    }
                }
            }

            if (!certainlyNotSolid)
            {
                return(pattern.Solid);
            }
            else if (!certainlyNotCV)
            {
                return(pattern.CleanVert);
            }
            else
            {
                return(pattern.CleanHorz);
            }
        }
Пример #23
0
        public override void Encode(IntField image, Stream output)
        {
            /// Split background from foreground. Anything with low "rectangularity" goes into foreground
            /// - measure the number of "turns" (changes from horz to vert edge) against area.
            /// Background:
            /// - Predictive xform with small radius
            /// - Modified runlengths
            /// - Context-aware arithmetic encoding
            /// Foreground:
            /// - Order colors by how common they are, call them c1,c2,c3
            /// - Flatten all colors into 0 and 1
            /// - Find all rects covering all c2-pixels without covering any c1-pixels.
            /// - Find all rects covering all c3-pixels without covering any c1 or c2 pixels.
            /// - Predictive xform on 0/1 image stopping at vertical letter boundaries. If larger image not in dict, use a smaller one and add all sizes to dict.
            /// - Modified runlengths on the 0/1 xformed
            /// - Context-aware arithmetic encoding
            /// - Rects: optimize by changing 1 pixel rects to pixels; then feed optim ints through arithmetic
            /// Modified runlengths:
            /// - As before, encode only runs of 0's.
            /// - Every run longer than thresh encoded as thresh + a number in a separate optim stream
            /// - Optim stream is fed through arithmetic
            ///
            /// Alternative color encoding: a stream of 1's, 2's, 3's, fed through runlength

            image.ArgbTo4c();
            AddImageGrayscale(image, 0, 3, "00-original");
            IntField backgr, foregr;

            backgroundSplit(image, out backgr, out foregr);

            // Backgr
            backgr.PredictionEnTransformXor(new FixedSizeForeseer(5, 3, 2, new HorzVertForeseer()));
            AddImageGrayscale(backgr, 0, 3, "20-bkg-xformed");


            saveColors(foregr);

            // save as much as possible using rects, the rest just dumping as-is

            // Foregr
            IntField foremap = foregr.Clone();

            foremap.Map(pix => pix == 0 ? 0 : 1);
            AddImageGrayscale(foremap, 0, 1, "30-fore-map");
            foremap.PredictionEnTransformXor(new FixedSizeForeseer(7, 7, 3, new HorzVertForeseer()));
            AddImageGrayscale(foremap, 0, 1, "31-fore-map-xformed");

            saveForeground(foremap.Data);
        }
Пример #24
0
        public override void Learn(IntField image, int x, int y, int actual, int predicted)
        {
            if (_curArea == null)
            {
                _fallback.Learn(image, x, y, actual, predicted);
                return;
            }

            if (!_history.ContainsKey(_curArea))
            {
                _history.Add(_curArea, new ColorFrequencies());
            }

            _history[_curArea].Learn(actual);
        }
Пример #25
0
        public void Transpose()
        {
            var result = new IntField(Height, Width);

            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    result[y, x] = this[x, y];
                }
            }
            Width  = result.Width;
            Height = result.Height;
            Data   = result.Data;
        }
Пример #26
0
        /// <summary>
        /// Compresses a single file using a given compressor, saving all debug or
        /// visualisation outputs to the specified directory.
        /// </summary>
        public static void CompressFile(Compressor compr, string sourcePath, string destDir, string destFile)
        {
            IntField image = new IntField(0, 0);

            image.ArgbLoadFromFile(sourcePath);

            Directory.CreateDirectory(destDir);
            compr.AddImageArgb(image, "orig");
            using (var output = File.Open(Path.Combine(destDir, destFile), FileMode.Create, FileAccess.Write, FileShare.Read))
                compr.Encode(image, output);

            SaveComprImages(compr, destDir);
            SaveComprDumps(compr, destDir);
            SaveComprCounters(compr, destDir);
        }
Пример #27
0
        public override void Learn(IntField image, int x, int y, int actual, int predicted)
        {
            _fallback.Learn(image, x, y, actual, predicted);

            foreach (var area in _curAreas)
            {
                ColorFrequencies cf;
                if (!_history.TryGetValue(area, out cf))
                {
                    _history.Add(area, cf = new ColorFrequencies());
                }

                cf.Learn(actual);
            }
        }
Пример #28
0
        public override void Encode(IntField image, Stream output)
        {
            image.ArgbTo4c();
            AddImageGrayscale(image, "res0");
            List <IntField> scales = new List <IntField>();

            scales.Add(image);
            while (scales.Last().Width > 100 && scales.Last().Height > 100)
            {
                scales.Add(scales.Last().HalfResHighestCount());
            }

            for (int i = 1; i < scales.Count; i++)
            {
                IntField predicted = new IntField(scales[i - 1].Width, scales[i - 1].Height);
                IntField shrunk    = scales[i];
                AddImageGrayscale(shrunk, "res" + i);
                for (int y = 0; y < predicted.Height; y++)
                {
                    for (int x = 0; x < predicted.Width; x++)
                    {
                        int xm2 = x & 1;
                        int ym2 = y & 1;
                        int xd2 = x >> 1;
                        int yd2 = y >> 1;
                        if (xm2 == 0 && ym2 == 0) // original
                        {
                            predicted[x, y] = shrunk[xd2, yd2];
                        }
                        else if (ym2 == 0) // between horizontal pixels
                        {
                            predicted[x, y] = shrunk[xd2, yd2];
                        }
                        else
                        {
                            predicted[x, y] = shrunk[xd2, yd2];
                        }
                    }
                }
                //AddImageGrayscale(predicted, "pred"+i);
                for (int p = 0; p < predicted.Data.Length; p++)
                {
                    predicted.Data[p] ^= scales[i - 1].Data[p];
                }
                //AddImageGrayscale(predicted, "diff"+i);
            }
        }
Пример #29
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);
        }
Пример #30
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);
        }