{"id":13514805,"url":"https://github.com/knowledgepicker/word-cloud","last_synced_at":"2025-03-31T03:31:30.700Z","repository":{"id":39891068,"uuid":"342537016","full_name":"knowledgepicker/word-cloud","owner":"knowledgepicker","description":"Fast word cloud library for .NET. Uses Quadtrees for blazing-fast performance. Maintained by the KnowledgePicker team.","archived":false,"fork":false,"pushed_at":"2025-02-23T14:14:25.000Z","size":5595,"stargazers_count":29,"open_issues_count":2,"forks_count":8,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-23T15:22:20.242Z","etag":null,"topics":["netstandard20","tag-cloud","tagcloud","word-cloud","wordcloud","wordle"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/KnowledgePicker.WordCloud/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/knowledgepicker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"jjonescz","custom":"https://www.paypal.me/jjonescz"}},"created_at":"2021-02-26T10:11:45.000Z","updated_at":"2025-02-23T14:14:28.000Z","dependencies_parsed_at":"2023-10-17T10:50:19.609Z","dependency_job_id":"a91394ce-6e42-43e2-a82b-22ae1e9369f2","html_url":"https://github.com/knowledgepicker/word-cloud","commit_stats":{"total_commits":67,"total_committers":5,"mean_commits":13.4,"dds":"0.23880597014925375","last_synced_commit":"e0f1ce9106be913a2ea571166bfb6e3c72b08577"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knowledgepicker%2Fword-cloud","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knowledgepicker%2Fword-cloud/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knowledgepicker%2Fword-cloud/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knowledgepicker%2Fword-cloud/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/knowledgepicker","download_url":"https://codeload.github.com/knowledgepicker/word-cloud/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246413377,"owners_count":20773053,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["netstandard20","tag-cloud","tagcloud","word-cloud","wordcloud","wordle"],"created_at":"2024-08-01T05:01:02.036Z","updated_at":"2025-03-31T03:31:25.693Z","avatar_url":"https://github.com/knowledgepicker.png","language":"C#","funding_links":["https://github.com/sponsors/jjonescz","https://www.paypal.me/jjonescz"],"categories":["C#"],"sub_categories":[],"readme":"# WordCloud for .NET\n\n[![Nuget](https://img.shields.io/nuget/v/KnowledgePicker.WordCloud?logo=nuget)](https://www.nuget.org/packages/KnowledgePicker.WordCloud/)\n[![GitHub](https://img.shields.io/github/last-commit/knowledgepicker/word-cloud/master?logo=github)](https://github.com/knowledgepicker/word-cloud)\n\n`KnowledgePicker.WordCloud` is a modern (.NET Standard 2.0) and fast library for arranging and drawing [word clouds](https://knowledgepicker.com/t/427/tag-word-cloud) (a.k.a. tag clouds or wordle). It uses Quadtrees for blazing-fast performance. It is maintained by the [KnowledgePicker](https://knowledgepicker.com) team.\n\n\u003c!--\n  URL needs to be used, so the README works on NuGet.org. See also\n  https://learn.microsoft.com/en-us/nuget/nuget-org/package-readme-on-nuget-org#allowed-domains-for-images-and-badges.\n--\u003e\n![Sample Word Cloud](https://raw.githubusercontent.com/knowledgepicker/word-cloud/master/example.png)\n\n## How to use\n\n1. Install [NuGet package `KnowledgePicker.WordCloud`](https://www.nuget.org/packages/KnowledgePicker.WordCloud/).\n\n   \u003e **Note** There's currently only one drawing engine based on [SkiaSharp](https://github.com/mono/SkiaSharp). On some platforms, additional dependencies need to be installed to make SkiaSharp work correctly. For example, on Linux, add [SkiaSharp.NativeAssets.Linux](https://www.nuget.org/packages/SkiaSharp.NativeAssets.Linux); for Blazor WebAssembly, add [SkiaSharp.Views.Blazor](https://www.nuget.org/packages/SkiaSharp.Views.Blazor).\n\n2. Get collection of `WordCloudEntry`s. For example, suppose we have dictionary of word frequencies:\n\n   ```cs\n   var frequencies = new Dictionary\u003cstring, int\u003e();\n   // ...collect word frequencies somehow...\n   IEnumerable\u003cWordCloudEntry\u003e wordEntries = frequencies.Select(p =\u003e new WordCloudEntry(p.Key, p.Value));\n   ```\n\n3. Create world cloud configuration:\n\n   ```cs\n   var wordCloud = new WordCloudInput(wordEntries)\n   {\n       Width = 1024,\n       Height = 256,\n       MinFontSize = 8,\n       MaxFontSize = 32\n   };\n   ```\n\n4. We need to create drawing engine, font sizer and layout. Currently, we use [SkiaSharp](https://github.com/mono/SkiaSharp) for fast cross-platform font measuring (and drawing). We also only support logarithmic font sizes and spiral layout. All these things are implemented in a generic way and can be easily extended (contributions are welcome).\n\n   ```cs\n   var sizer = new LogSizer(wordCloud);\n   using var engine = new SkGraphicEngine(sizer, wordCloud);\n   var layout = new SpiralLayout(wordCloud);\n   var colorizer = new RandomColorizer(); // optional\n   var wcg = new WordCloudGenerator\u003cSKBitmap\u003e(wordCloud, engine, layout, colorizer);\n   ```\n\n   You can also use `SpecificColorizer` to colorize specific words with chosen colors:\n\n   ```cs\n   var colorizer = new SpecificColorizer(\n       new Dictionary\u003cstring, Color\u003e\n       {\n           [\"KnowledgePicker\"] = Color.FromArgb(0x0f3057),\n           [\"WordCloud\"] = Color.FromArgb(0xe25a5a)\n       },\n       fallback: new RandomColorizer()); // fallback argument is optional\n   ```\n\n   You can also optionally pass a font into the graphic engine:\n\n   ```cs\n   var typeface = SKTypeface.FromFamilyName(\"DejaVu Serif\", SKFontStyle.Normal);\n   using var engine = new SkGraphicEngine(sizer, wordCloud, typeface);\n   ```\n\n5. Now we can *arrange* the topic cloud:\n\n   ```cs\n   IEnumerable\u003c(LayoutItem Item, double FontSize)\u003e items = wcg.Arrange();\n   ```\n\n   And if we are in a Razor view of an ASP.NET Core application, for example, we can generate SVG from `items`:\n\n   ```cshtml\n   \u003csvg viewBox=\"0,0,@wordCloud.Width,@wordCloud.Height\"\u003e\n   @foreach (var (item, fontSize) in items)\n   {\n       const string format = \"0.##\"; // Use at most 2 decimal places.\n       var x = (item.Location.X - item.Measured.Left).ToString(format);\n       var y = (item.Location.Y - item.Measured.Top).ToString(format);\n       var fs = fontSize.ToString(format);\n       var color = wcg.GetColorHexString(item);\n       \u003ctext transform=\"translate(@x, @y)\" font-size=\"@fs\" fill=\"@color\"\u003e@item.Entry.Word\u003c/text\u003e\n   }\n   \u003c/svg\u003e\n   ```\n\n6. Alternatively, we can *draw* the topic cloud (see also [example `WordFrequencies.ConsoleApp`](https://github.com/knowledgepicker/word-cloud/tree/master/examples/WordFrequency.ConsoleApp)):\n\n   ```cs\n   using var final = new SKBitmap(wordCloud.Width, wordCloud.Height);\n   using var canvas = new SKCanvas(final);\n\n   // Draw on white background.\n   canvas.Clear(SKColors.White);\n   using var bitmap = wcg.Draw();\n   canvas.DrawBitmap(bitmap, 0, 0);\n\n   // Save to PNG.\n   using var data = final.Encode(SKEncodedImageFormat.Png, 100);\n   using var writer = File.Create(\"output.png\");\n   data.SaveTo(writer);\n   ```\n\n## Algorithm\n\nThe world cloud algorithm was initially ported from [SourceCodeCloud](https://archive.codeplex.com/?p=sourcecodecloud). It uses [Quadtrees](https://en.wikipedia.org/wiki/Quadtree), hence it should be reasonably fast. It is inspired by [implementation of Wordle](https://stackoverflow.com/a/1478314) (once famous algorithm used on\nnow-defunct site [wordle.net](https://web.archive.org/web/20201206102909/http://www.wordle.net/)).\n\n## Examples\n\nSimple console application which draws word cloud PNG for words given on its standard input is [`WordFrequencies.ConsoleApp`](examples/WordFrequency.ConsoleApp).\n\nThis library is also used in production by [KnowledgePicker](https://knowledgepicker.com). They use it to draw [topic clouds for user profiles](https://knowledgepicker.com/profiles).\n\n## Contributing\n\nAs mentioned [above](#how-to-use), only subset of functionality is implemented now, but all contributions are welcome. Feel free to open [issues](https://github.com/knowledgepicker/word-cloud/issues) and [pull requests](https://github.com/knowledgepicker/word-cloud/pulls).\n\n### Testing\n\nTests are currently only supported on Linux, because they are snapshot tests (generating a word cloud image and comparing it byte-by-byte with a snapshot) and more work is needed to ensure this is cross-platform (e.g., use exactly the same font). On Windows, tests can be run in WSL (Visual Studio supports this directly). Tests are also automatically run in GitHub Actions.\n\n### Release process\n\nAfter pushing a tag, GitHub workflow `release.yml` is triggered which builds and publishes the NuGet package.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknowledgepicker%2Fword-cloud","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknowledgepicker%2Fword-cloud","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknowledgepicker%2Fword-cloud/lists"}