コード例 #1
0
        public unsafe HybridMap2(IFontProvider fontProvider, IPixelFormatProvider pixelFormatProvider,
                                 string fullMapPath, string refMapPath, string refFontPath, int coreCount, int partitionsPerDim, int?partitionDepth)
        {
            if (coreCount < 1)
            {
                coreCount = System.Environment.ProcessorCount - coreCount;
            }

            this.FontProvider        = fontProvider;
            this.PixelFormatProvider = pixelFormatProvider;
            this.FontProvider.Init(this.PixelFormatProvider.DiscreteNormalizedValues.Length);

            Log.WriteLine("  DiscreteNormalizedValues:");
            for (int i = 0; i < PixelFormatProvider.DiscreteNormalizedValues.Length; ++i)
            {
                if (i > 14)
                {
                    Log.WriteLine("    ...");
                    break;
                }
                Log.WriteLine("    {0}: {1,10:0.00}", i, PixelFormatProvider.DiscreteNormalizedValues[i]);
            }

            Log.WriteLine("Number of source chars (1d): " + this.FontProvider.CharCount.ToString("N0"));
            Log.WriteLine("Chosen values per tile: " + pixelFormatProvider.DiscreteNormalizedValues.Length);
            Log.WriteLine("Dimensions: " + PixelFormatProvider.DimensionCount);
            Log.WriteLine("Resulting map will have this many entries: " + pixelFormatProvider.MapEntryCount.ToString("N0"));
            long mapdimpix = (long)Math.Sqrt(pixelFormatProvider.MapEntryCount);

            Log.WriteLine("Resulting map will be about: [" + mapdimpix.ToString("N0") + ", " + mapdimpix.ToString("N0") + "]");

            // fill in char source info (actual tile values)
            Log.EnterTask("Analyze incoming font");
            this.CharInfo = new CharInfo[FontProvider.CharCount];// new List<CharInfo>();

            for (int ichar = 0; ichar < FontProvider.CharCount; ++ichar)
            {
                var ci = new CharInfo(PixelFormatProvider.DimensionCount)
                {
                    srcIndex = ichar,
#if DEBUG
                    //fontImageCellPos = FontProvider.GetCharPosInChars(ichar),
                    //fontImagePixelPos = FontProvider.GetCharOriginInPixels(ichar),
#endif
                };
                pixelFormatProvider.PopulateCharColorData(ci, fontProvider);
                this.CharInfo[ichar] = ci;
            }

            Log.WriteLine("Number of source chars: " + this.CharInfo.Length);

            PartitionManager pm = new PartitionManager(partitionsPerDim, partitionDepth.GetValueOrDefault(PixelFormatProvider.DimensionCount + 1), PixelFormatProvider.DiscreteNormalizedValues);

            // create list of all mapkeys
            Log.EnterTask("Generating {0:N0} map key indices", pixelFormatProvider.MapEntryCount);
            this.Keys = Utils.Permutate(PixelFormatProvider.DimensionCount, pixelFormatProvider.DiscreteNormalizedValues); // returns sorted.
            // populate the denormalized values
            for (int i = 0; i < this.Keys.Length; ++i)
            {
                this.Keys[i].DenormalizedValues = this.PixelFormatProvider.Denormalize(this.Keys[i].NormalizedValues);
            }

            Log.EndTask();

            Log.WriteLine("Key count: " + this.Keys.Length);

            foreach (var ci in this.CharInfo)
            {
                pm.AddItem(ci);
            }

            Log.EndTask();
            Log.EnterTask("Calculate all mappings");

            // - generate a list of mappings and their distances
            ulong theoreticalMappings = (ulong)this.CharInfo.Length * (ulong)pixelFormatProvider.MapEntryCount;

            Log.WriteLine("  Theoretical mapping count: " + theoreticalMappings.ToString("N0"));

            List <Task> comparisonBatches = new List <Task>();
            var         Map = new Mapping[Keys.Length];// indices need to be synchronized with Keys.

            for (int icore = 0; icore < coreCount; ++icore)
            {
                // create a task to process a segment of keys
                ulong keyBegin = (ulong)icore;
                keyBegin *= (ulong)Keys.Length;
                keyBegin /= (ulong)coreCount;

                ulong keyEnd = (ulong)icore + 1;
                keyEnd *= (ulong)Keys.Length;
                keyEnd /= (ulong)coreCount;

                int  coreID     = icore;
                bool isLastCore = (icore == coreCount - 1);

                comparisonBatches.Add(Task.Run(() =>
                {
                    PopulateMap(keyBegin, keyEnd, coreID, isLastCore, pm, Map);
                }));
            }
            Task.WaitAll(comparisonBatches.ToArray());
            Log.EndTask();

            // todo: a histogram would be more informative than this crap.
            int      numCharsUsed     = 0;
            int      numCharsUsedOnce = 0;
            CharInfo mostUsedChar     = null;
            int      numRepetitions   = 0;

            foreach (var ci in this.CharInfo)
            {
                if (mostUsedChar == null || mostUsedChar.usages < ci.usages)
                {
                    mostUsedChar = ci;
                }
                if (ci.usages > 0)
                {
                    numCharsUsed++;
                }
                if (ci.usages == 1)
                {
                    numCharsUsedOnce++;
                }
                if (ci.usages > 1)
                {
                    numRepetitions += ci.usages - 1;
                }
            }

            Log.WriteLine("Process currently using {0:0.00} mb of memory)", Utils.BytesToMb(Utils.UsedMemoryBytes));

#if false
            OutputFullMap(fullMapPath, Map);
#endif

            DistinctMappedChars = Map.DistinctBy(o => o.icharInfo).Select(o => this.CharInfo[o.icharInfo]).ToArray();
            for (int ichar = 0; ichar < DistinctMappedChars.Length; ++ichar)
            {
                CharInfo ci = DistinctMappedChars[ichar];
                Debug.Assert(ci != null);
                ci.refFontIndex = ichar;
            }

            OutputRefMapAndFont(refMapPath, refFontPath, Map);


            // save data structures
            string jsonDistinctMappedChars = Newtonsoft.Json.JsonConvert.SerializeObject(DistinctMappedChars, Newtonsoft.Json.Formatting.Indented);
            System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\DistinctMappedChars.json"), jsonDistinctMappedChars);

            //string jsonKeys = Newtonsoft.Json.JsonConvert.SerializeObject(Keys, Newtonsoft.Json.Formatting.Indented);
            //System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\Keys.json"), jsonKeys);

            string jsonCharInfo = Newtonsoft.Json.JsonConvert.SerializeObject(CharInfo, Newtonsoft.Json.Formatting.Indented);
            System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\CharInfo.json"), jsonCharInfo);

            //string jsonMap = Newtonsoft.Json.JsonConvert.SerializeObject(Map, Newtonsoft.Json.Formatting.Indented);
            //System.IO.File.WriteAllText(System.IO.Path.Combine(refMapPath, "..\\Map.json"), jsonMap);

            Log.WriteLine("Post-map stats:");
            Log.WriteLine("  Used char count: " + numCharsUsed);
            Log.WriteLine("  Number of unused char: " + (this.CharInfo.Length - numCharsUsed));
            Log.WriteLine("  Number of chars used exactly once: " + numCharsUsedOnce);
            Log.WriteLine("  Most-used char: " + mostUsedChar + " (" + mostUsedChar.usages + ") usages");
            Log.WriteLine("  Number of total char repetitions: " + numRepetitions);
        }
コード例 #2
0
        private void PopulateMap(ulong keyBegin, ulong keyEnd, int coreID, bool isLastCore, PartitionManager pm, Mapping[] Map)
        {
            int mapEntriesToPopulate = (int)keyEnd - (int)keyBegin;

            Log.WriteLine("    Batch processing idx {0:N0} to {1:N0}", keyBegin, keyEnd);
            var pr = isLastCore ? new ProgressReporter((ulong)mapEntriesToPopulate) : null;

            for (int ikey = (int)keyBegin; ikey < (int)keyEnd; ++ikey)
            {
                pr?.Visit((ulong)ikey - keyBegin);
                var    chars = pm.GetItemsInSamePartition(this.Keys[ikey]);
                double p     = ikey - (int)keyBegin;
                p /= keyEnd - keyBegin;

                CharInfo ciNearest   = null;
                double   closestDist = double.MaxValue;

                //foreach (var ci in chars)
                for (int ichar = 0; ichar < chars.Length; ++ichar)
                {
                    var    ci    = chars[ichar];
                    double fdist = this.PixelFormatProvider.CalcKeyToColorDist(this.Keys[ikey], ci.actualValues);
                    if (fdist < closestDist)
                    {
                        this.Keys[ikey].MinDistFound = fdist;// Math.Min(this.Keys[ikey].MinDistFound, fdist);
                        closestDist = fdist;
                        ciNearest   = ci;
                    }
                }

                Map[ikey].dist      = closestDist;
                Map[ikey].icharInfo = ciNearest.srcIndex;
                ciNearest.usages++;
                Map[ikey].imapKey = ikey;
            }
        }