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); }
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); }
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); }
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); } }
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); }