{"id":13425778,"url":"https://github.com/kennycason/kumo","last_synced_at":"2025-10-21T04:41:59.816Z","repository":{"id":18301171,"uuid":"21477166","full_name":"kennycason/kumo","owner":"kennycason","description":"Kumo - Java Word Cloud ","archived":false,"fork":false,"pushed_at":"2025-06-04T17:53:37.000Z","size":38405,"stargazers_count":648,"open_issues_count":45,"forks_count":155,"subscribers_count":33,"default_branch":"master","last_synced_at":"2025-09-26T21:18:17.599Z","etag":null,"topics":["cloud","java","kumo","word-cloud","wordcloud"],"latest_commit_sha":null,"homepage":"http://kennycason.com/posts/2014-07-03-kumo-wordcloud.html","language":"Java","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/kennycason.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2014-07-03T21:14:53.000Z","updated_at":"2025-09-05T08:52:07.000Z","dependencies_parsed_at":"2023-09-24T07:15:56.388Z","dependency_job_id":null,"html_url":"https://github.com/kennycason/kumo","commit_stats":{"total_commits":259,"total_committers":20,"mean_commits":12.95,"dds":"0.33976833976833976","last_synced_commit":"a9b89d4f379f1323d0bd5bd364adb7940c389edf"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/kennycason/kumo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennycason%2Fkumo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennycason%2Fkumo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennycason%2Fkumo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennycason%2Fkumo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kennycason","download_url":"https://codeload.github.com/kennycason/kumo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennycason%2Fkumo/sbom","scorecard":{"id":555398,"data":{"date":"2025-08-11","repo":{"name":"github.com/kennycason/kumo","commit":"1c95daf7a1901854f55f39a01000cbe5c4edbe86"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":1,"reason":"Found 4/23 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 11 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T12:11:51.313Z","repository_id":18301171,"created_at":"2025-08-20T12:11:51.314Z","updated_at":"2025-08-20T12:11:51.314Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280207158,"owners_count":26290614,"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","status":"online","status_checked_at":"2025-10-21T02:00:06.614Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cloud","java","kumo","word-cloud","wordcloud"],"created_at":"2024-07-31T00:01:18.672Z","updated_at":"2025-10-21T04:41:59.809Z","avatar_url":"https://github.com/kennycason.png","language":"Java","funding_links":[],"categories":["Java"],"sub_categories":[],"readme":"\n\n# \u003cimg src=\"logo/Kumo02.png\" alt=\"Kumo\" height=\"28px\"\u003e Kumo\n\nKumo's goal is to create a powerful and user friendly Word Cloud API in Java. Kumo directly generates an image file without the need to create an applet as many other libraries do.\n\nPlease feel free to jump in and help improve Kumo! There are many places for performance optimization in Kumo!\n\nUPDATE: 2025-06-04. I plan on coming back to this project sometime to address issues, convert the project to Kotlin. Apologies for going dark \u003c3\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.kennycason/kumo-core/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/com.kennycason/kumo-core)  [![CircleCI](https://circleci.com/gh/kennycason/kumo.svg?style=svg)](https://circleci.com/gh/kennycason/kumo)\u003cbr/\u003e\n\n### Current Features\n\n- Draw Rectangle, Circle or Image Overlay word clouds. Image Overlay will draw words over all non-transparent pixels.\n- Linear, Square-Root Font Scalars. Fully extendable.\n- Variable Font Sizes.\n- Word Rotation. Just provide a Start Angle, End Angle, and number of slices.\n- Custom BackGround Color. Fully customizable BackGrounds coming soon.\n- Word Padding.\n- Load Custom Color Palettes. Also supports color gradients.\n- Two Modes that of Collision and Padding: PIXEL_PERFECT and RECTANGLE.\n- Polar Word Clouds. Draw two opposing word clouds in one image to easily compare/contrast date sets.\n- Layered Word Clouds. Overlay multiple word clouds.\n- WhiteSpace and Chinese Word Tokenizer. Fully extendable. \n- Frequency Analyzer to tokenize, filter and compute word counts.\n- Command Line Interface\n\n#### CLI Install via Brew (NEW!)\n\n`brew install kumo`\n\n### Available from Maven Central\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.kennycason\u003c/groupId\u003e\n    \u003cartifactId\u003ekumo-core\u003c/artifactId\u003e\n    \u003cversion\u003e1.28\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nInclude `kumo-tokenizers` if you want Chinese serialization. More languages to come.\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.kennycason\u003c/groupId\u003e\n    \u003cartifactId\u003ekumo-tokenizers\u003c/artifactId\u003e\n    \u003cversion\u003e1.28\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Screenshots\n\n\u003ctable\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/whale_wordcloud_large_impact.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/simplymeasured.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/layered_haskell.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/layered_pho_bowl.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/polar_newyork_rectangle_blur.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/polar_tide_chinese_vs_english2.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/datarank_wordcloud_circle_sqrt_font.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/chinese_language_circle.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/polar_newyork_whale_large_blur.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/layered_word_cloud.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/whale_wordcloud_large_angles.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/wordcloud_rectangle.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/wordcloud_gradient_redbluegreen.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/wordcloud_gradient_whiteredblue.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/bubbletext.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003ctd\u003e\n\u003cimg src=\"kumo-core/output/wordcloud_emoji.png?raw=true\" width=\"300\"/\u003e\n\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n### Examples\n\nExample to generate a Word Cloud on top of an image.\n\n```java\nfinal FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\nfrequencyAnalyzer.setWordFrequenciesToReturn(300);\nfrequencyAnalyzer.setMinWordLength(4);\nfrequencyAnalyzer.setStopWords(loadStopWords());\n\nfinal List\u003cWordFrequency\u003e wordFrequencies = frequencyAnalyzer.load(\"text/datarank.txt\");\nfinal Dimension dimension = new Dimension(500, 312);\nfinal WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT);\nwordCloud.setPadding(2);\nwordCloud.setBackground(new PixelBoundryBackground(\"backgrounds/whale_small.png\"));\nwordCloud.setColorPalette(new ColorPalette(new Color(0x4055F1), new Color(0x408DF1), new Color(0x40AAF1), new Color(0x40C5F1), new Color(0x40D3F1), new Color(0xFFFFFF)));\nwordCloud.setFontScalar(new LinearFontScalar(10, 40));\nwordCloud.build(wordFrequencies);\nwordCloud.writeToFile(\"kumo-core/output/whale_wordcloud_small.png\");\n```\n\nExample to generate a circular Word Cloud.\n\n```java\nfinal FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\nfinal List\u003cWordFrequency\u003e wordFrequencies = frequencyAnalyzer.load(\"text/my_text_file.txt\");\nfinal Dimension dimension = new Dimension(600, 600);\nfinal WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT);\nwordCloud.setPadding(2);\nwordCloud.setBackground(new CircleBackground(300));\nwordCloud.setColorPalette(new ColorPalette(new Color(0x4055F1), new Color(0x408DF1), new Color(0x40AAF1), new Color(0x40C5F1), new Color(0x40D3F1), new Color(0xFFFFFF)));\nwordCloud.setFontScalar(new SqrtFontScalar(10, 40));\nwordCloud.build(wordFrequencies);\nwordCloud.writeToFile(\"kumo-core/output/datarank_wordcloud_circle_sqrt_font.png\");\n```\n\nExample to generate a rectangle Word Cloud\n\n```java\nfinal FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\nfinal List\u003cWordFrequency\u003e wordFrequencies = frequencyAnalyzer.load(\"text/my_text_file.txt\");\nfinal Dimension dimension = new Dimension(600, 600);\nfinal WordCloud wordCloud = new WordCloud(dimension, CollisionMode.RECTANGLE);\nwordCloud.setPadding(0);\nwordCloud.setBackground(new RectangleBackground(dimension));\nwordCloud.setColorPalette(new ColorPalette(Color.RED, Color.GREEN, Color.YELLOW, Color.BLUE));\nwordCloud.setFontScalar(new LinearFontScalar(10, 40));\nwordCloud.build(wordFrequencies);\nwordCloud.writeToFile(\"kumo-core/output/wordcloud_rectangle.png\");\n```\n\n\nExample using Linear Color Gradients\n\n```java\nfinal FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\nfrequencyAnalyzer.setWordFrequenciesToReturn(500);\nfrequencyAnalyzer.setMinWordLength(4); \nfinal List\u003cWordFrequency\u003e wordFrequencies = frequencyAnalyzer.load(\"text/my_text_file.txt\");\nfinal Dimension dimension = new Dimension(600, 600);\nfinal WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT);\nwordCloud.setPadding(2);\nwordCloud.setBackground(new CircleBackground(300));\n// colors followed by and steps between\nwordCloud.setColorPalette(new LinearGradientColorPalette(Color.RED, Color.BLUE, Color.GREEN, 30, 30));\nwordCloud.setFontScalar( new SqrtFontScalar(10, 40));\nwordCloud.build(wordFrequencies);\nwordCloud.writeToFile(\"kumo-core/output/wordcloud_gradient_redbluegreen.png\");\n```\n\nExample of tokenizing chinese text into a circle\n\n```java\nfinal FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\nfrequencyAnalyzer.setWordFrequenciesToReturn(600);\nfrequencyAnalyzer.setMinWordLength(2);\nfrequencyAnalyzer.setWordTokenizer(new ChineseWordTokenizer());\n\nfinal List\u003cWordFrequency\u003e wordFrequencies = frequencyAnalyzer.load(\"text/chinese_language.txt\");\nfinal Dimension dimension = new Dimension(600, 600);\nfinal WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT);\nwordCloud.setPadding(2);\nwordCloud.setBackground(new CircleBackground(300));\nwordCloud.setColorPalette(new ColorPalette(new Color(0xD5CFFA), new Color(0xBBB1FA), new Color(0x9A8CF5), new Color(0x806EF5)));\nwordCloud.setFontScalar(new SqrtFontScalar(12, 45));\nwordCloud.build(wordFrequencies);\nwordCloud.writeToFile(\"kumo-core/output/chinese_language_circle.png\");\n```\n\nCreate a polarity word cloud to contrast two datasets\n\n```java\nfinal FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\nfrequencyAnalyzer.setWordFrequenciesToReturn(750);\nfrequencyAnalyzer.setMinWordLength(4);\nfrequencyAnalyzer.setStopWords(loadStopWords());\n\nfinal List\u003cWordFrequency\u003e wordFrequencies = frequencyAnalyzer.load(\"text/new_york_positive.txt\");\nfinal List\u003cWordFrequency\u003e wordFrequencies2 = frequencyAnalyzer.load(\"text/new_york_negative.txt\");\nfinal Dimension dimension = new Dimension(600, 600);\nfinal PolarWordCloud wordCloud = new PolarWordCloud(dimension, CollisionMode.PIXEL_PERFECT, PolarBlendMode.BLUR);\nwordCloud.setPadding(2);\nwordCloud.setBackground(new CircleBackground(300));\nwordCloud.setFontScalar(new SqrtFontScalar(10, 40));\nwordCloud.build(wordFrequencies, wordFrequencies2);\nwordCloud.writeToFile(\"kumo-core/output/polar_newyork_circle_blur_sqrt_font.png\");\n```\n\n\nCreate a Layered Word Cloud from two images/two word sets\n\n```java\nfinal FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\nfrequencyAnalyzer.setWordFrequenciesToReturn(300);\nfrequencyAnalyzer.setMinWordLength(5);\nfrequencyAnalyzer.setStopWords(loadStopWords());\n\nfinal List\u003cWordFrequency\u003e wordFrequencies = frequencyAnalyzer.load(\"text/new_york_positive.txt\");\nfinal List\u003cWordFrequency\u003e wordFrequencies2 = frequencyAnalyzer.load(\"text/new_york_negative.txt\");\nfinal Dimension dimension = new Dimension(600, 386);\nfinal LayeredWordCloud layeredWordCloud = new LayeredWordCloud(2, dimension, CollisionMode.PIXEL_PERFECT);\n\nlayeredWordCloud.setPadding(0, 1);\nlayeredWordCloud.setPadding(1, 1);\n\nlayeredWordCloud.setFontOptions(0, new KumoFont(\"LICENSE PLATE\", FontWeight.BOLD));\nlayeredWordCloud.setFontOptions(1, new KumoFont(\"Comic Sans MS\", FontWeight.BOLD));\n\nlayeredWordCloud.setBackground(0, new PixelBoundryBackground(\"backgrounds/cloud_bg.bmp\"));\nlayeredWordCloud.setBackground(1, new PixelBoundryBackground(\"backgrounds/cloud_fg.bmp\"));\n\nlayeredWordCloud.setColorPalette(0, new ColorPalette(new Color(0xABEDFF), new Color(0x82E4FF), new Color(0x55D6FA)));\nlayeredWordCloud.setColorPalette(1, new ColorPalette(new Color(0xFFFFFF), new Color(0xDCDDDE), new Color(0xCCCCCC)));\n\nlayeredWordCloud.setFontScalar(0, new SqrtFontScalar(10, 40));\nlayeredWordCloud.setFontScalar(1, new SqrtFontScalar(10, 40));\n\nlayeredWordCloud.build(0, wordFrequencies);\nlayeredWordCloud.build(1, wordFrequencies2);\nlayeredWordCloud.writeToFile(\"kumo-core/output/layered_word_cloud.png\");\n```\n\nCreate a ParallelLayeredWordCloud using 4 distinct Rectangles.\u003cbr\u003e\nEvery Rectangle will be processed in a separate thread, thus minimizing build-time significantly\nNOTE: This will eventually be natively handled along with better internal data structures.\n\n```java\nfinal Dimension dimension = new Dimension(2000, 2000);\nParallelLayeredWordCloud parallelLayeredWordCloud = new ParallelLayeredWordCloud(4, dimension, CollisionMode.PIXEL_PERFECT);\n\n// Setup parts for word clouds\nfinal Normalizer[] NORMALIZERS = new Normalizer[] { \n    new UpperCaseNormalizer(), \n    new LowerCaseNormalizer(),\n    new BubbleTextNormalizer(),\n    new StringToHexNormalizer() \n};\nfinal Font[] FONTS = new Font[] { \n            new Font(\"Lucida Sans\", Font.PLAIN, 10), \n            new Font(\"Comic Sans\", Font.PLAIN, 10),\n            new Font(\"Yu Gothic Light\", Font.PLAIN, 10), \n            new Font(\"Meiryo\", Font.PLAIN, 10) \n};\nfinal List\u003cList\u003cWordFrequency\u003e\u003e listOfWordFrequencies = new ArrayList\u003c\u003e();\nfinal Point[] positions = new Point][] { new Point(0, 0), new Point(0, 1000), new Point(1000, 0), new Point(1000, 1000) };\nfinal Color[] colors = new Color[] { Color.RED, Color.WHITE, new Color(0x008080)/* TEAL */, Color.GREEN };\n\n// set up word clouds\nfor (int i = 0; i \u003c lwc.getLayers(); i++) {\n    final FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();\n    frequencyAnalyzer.setMinWordLength(3);\n    frequencyAnalyzer.setNormalizer(NORMALIZERS[i]);\n    frequencyAnalyzer.setWordFrequenciesToReturn(1000);\n    listOfWordFrequencies.add(frequencyAnalyzer.load(\"text/english_tide.txt\"));\n\n    final WordCloud worldCloud = parallelLayeredWordCloud.getAt(i);\n    worldCloud.setAngleGenerator(new AngleGenerator(0));\n    worldCloud.setPadding(3);\n    worldCloud.setWordStartStrategy(new CenterWordStart());\n    worldCloud.setKumoFont(new KumoFont(FONTS[i]));\n    worldCloud.setColorPalette(new ColorPalette(colors[i]));\n\n    worldCloud.setBackground(new RectangleBackground(positions[i], dimension));\n    worldCloud.setFontScalar(new LinearFontScalar(10, 40));\n}\n\n// start building\nfor (int i = 0; i \u003c lwc.getLayers(); i++) {\n    parallelLayeredWordCloud.build(i, listOfWordFreqs.get(i));\n}\n\nparallelLayeredWordCloud.writeToFile(\"parallelBubbleText.png\");\n```\n\nRefer to JPanelDemo.java for an example integrating into a JPanel.\n\n\n### Word Frequency File / Analyzer\n\nThe most common way to generate word frequencies is to pass a String of text directly to `FrequencyAnalyzer`.\nThe `FrequencyAnalyzer` contains many options to process and normalize input text.\n\nSometimes the word counts and word frequencies are already known and a consumer would like to load them directly into Kumo.\nTo do so, you can manually construct the `List\u003cWordFrequency\u003e` yourself, or you can load in a text file containing the word frequency and word pairs.\nThe `FrequencyFileLoader` can be used to load such files. The required format is:\n```\n100: frog\n94: dog\n43: cog\n20: bog\n3: fog\n1: log\n1: pog\n```\n\nOrder does not matter as the `FrequencyFileLoader` will automatically sort the pairs.\n\n### Tokenizers\n\nTokenizers are the code that splits a sentence/text into a list of words. Currently only two tokenizers are built into Kumo.\nTo add your own just create a class that override the `Tokenizer` interface and call the `FrequencyAnalyzer.setTokenizer()` or `FrequencyAnalyzer.addTokenizer()`.\n\n| Tokenizer   |\n|-------------|\n| WhiteSpaceWordTokenizer |\n| ChineseWordTokenizer |\n\n\n### Filters\n\nAfter tokenization, filters are applied to each word to determine whether or not should be omitted from the word list. \n\nTo add set the filter, call `FrequencyAnalyzer.setFilter()` or `FrequencyAnalyzer.addFilter()`\n\n\n| Tokenizer   | Description |\n|-------------|-------------|\n| UrlFilter | A filter to remove words that are urls. |\n| CompositeFilter | A wrapper of a collection of filters. |\n| StopWordFilter | Internally used, the FrequencyAnalyzer makes this filter easy to use via `FrequencyAnalyzer.setStopWords()`. |\n| WordSizeFilter | Internally used, the FrequencyAnalyzer makes this filter easy to use via `FrequencyAnalyzer.setMinWordLength()` and `FrequencyAnalyzer.setMaxWordLength()`. |\n\n### Normalizers\n\nAfter word tokenization and filtering has occurred you can further transform each word via a normalizer.\nThe default normalizer ia `lowerCase•characterStripping*trimToEmpty(word)`, the normalizer is even named `DefaultNormalizer`\n\nTo add set the normalizer, call `FrequencyAnalyzer.setNormalizer()` or `FrequencyAnalyzer.addNormalizer()`\n\n| Normalizers | Description |\n|-------------|-------------|\n| CharacterStrippingNormalizer | Constructed with a Pattern, it will replace all matched occurrences with a configurable 'replaceWith' string. The default pattern is `\\\\.|:|;|\\\\(|\\\\)|\\\"|,|\\\\?|,|!|\u003c|\u003e|/`|\n| LowerCaseNormalizer | Converts all text to lowercase. |\n| UpperCaseNormalizer | Converts all text to uppercase. |\n| TrimToEmptyNormalizer | Trims the text down to an empty string, even if null. |\n| UpsideDownNormalizer | Converts A-Z,a-z,0-9 character to an upside-down variant. |\n| StringToHexNormalizer | Converts each character to it's hex value and concatenates them. |\n| DefaultNormalizer | Combines the TrimToEmptyNormalizer, CharacterStrippingNormalizer, and LowerCaseNormalizer. |\n| BubbleTextNormalizer | Replaces A-Z,a-z with characters enclosed in Bubbles ⓐ-ⓩⒶ-Ⓩ (requires a supporting font) |\n\n\n### Command Line Interface (CLI)\n\nKumo can now be accessed via CLI. It is not quite as flexible as the programmatic interface yet but should support most of the common needs.\n\nThe CLI Documentation can be found [here](https://github.com/kennycason/kumo/blob/master/CLI.md).\n\nThe below examples assume you have the jar installed under the name of \"kumo\". To install via Brew run the following command.\n\n`brew install https://raw.githubusercontent.com/kennycason/kumo/master/script/kumo.rb`\n\nExamples:\n\nCreate a standard word cloud.\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\"\n```\n\nCreate a standard word cloud excluding stop words.\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\" --stop-words \"nintendo,the\"\n```\n\nCreate a standard word cloud with a limited word count.\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\" --word-count 10\n```\n\nCreate a standard word cloud with a custom width and height.\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\" --width 256 --height 256\n```\n\nCreate a standard word cloud with custom font configuration.\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\" --font-scalar sqrt --font-type Impact --font-weight plain --font-size-min 4 --font-size-max 60\n```\n\nCreate a standard word cloud with a custom shape.\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\" --width 990 --height 618 --background \"https://raw.githubusercontent.com/kennycason/kumo/master/src/test/resources/backgrounds/whale.png\n```\n\nCreate a standard word cloud with a custom color palette.\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\" --color \"(255,0,0),(0,255,0),(0,0,255)\"\n```\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo\" --output \"/tmp/wordcloud.png\" --color \"(0xffffff),(0xcccccc),(0x999999),(0x666666),(0x333333)\"\n```\n\nCreate a standard word cloud using a Chinese tokenizer\n```\nkumo --input \"https://zh.wikipedia.org/wiki/%E4%BB%BB%E5%A4%A9%E5%A0%82\" --output \"/tmp/wordcloud.png\" --tokenizer chinese\n```\n\nCreate a polar word cloud\n```\nkumo --input \"https://en.wikipedia.org/wiki/Nintendo,https://en.wikipedia.org/wiki/PlayStation\" --output \"/tmp/nintendo_vs_playstation.png\" --type polar --color \"(0x00ff00),(0x00dd00),(0x007700)|(0xff0000),(0xdd0000),(0x770000)\"\n```\n\nCreate a layered word cloud\n```\nkumo --input \"https://www.haskell.org/, https://en.wikipedia.org/wiki/Haskell_(programming_language)\" --output \"/tmp/nintendo_vs_playstation.png\" --type layered --background \"https://raw.githubusercontent.com/kennycason/kumo/master/src/test/resources/backgrounds/haskell_1.bmp,https://raw.githubusercontent.com/kennycason/kumo/master/src/test/resources/backgrounds/haskell_2.bmp\" --color \"(0xFA6C07),(0xFF7614),(0xFF8936)|(0x080706),(0x3B3029),(0x47362A)\"\n```\n\n\n### Contributing\n\nMy primary IDE of choice is IntelliJ due to their robust tooling as well as code analysis/inspections. If using [IntelliJ IDEA](https://www.jetbrains.com/idea/), I recommend importing `KumoIntelliJInspections.xml`. I am also considering adding Checkstyle support.\n\nNew tests that write images should write images out to `kumo-core/output_test/` instead of `kumo-core/output/` which is now used for images to showcase Kumo.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkennycason%2Fkumo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkennycason%2Fkumo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkennycason%2Fkumo/lists"}