Add support for custom bitmaps and docs

This commit is contained in:
xtreak 2018-03-22 21:45:38 +05:30
parent 48f5ddc293
commit 8f76e1175a
10 changed files with 206 additions and 27 deletions

View file

@ -1,5 +1,9 @@
This library is a wrapper around [kumo](https://github.com/kennycason/kumo) . You can look into the source for things to port. Fork and make a PR.
## API guidelines
* API should be compatible with [kumo](https://github.com/kennycason/kumo) and please refer to the repo for implementing new APIs.
## Code guidelines
* Please use [aligned maps](https://github.com/bbatsov/clojure-style-guide#vertically-align-let-and-map) . In emacs select the map and hit `C-c SPC`. Refer : https://github.com/clojure-emacs/clojure-mode#vertical-alignment

View file

@ -6,18 +6,69 @@ A simple clojure wrapper around kumo to generate wordcloud
Given a map of element and the frequency the following image is generated. More examples/examples.clj.
### Circle
```clojure
(let [frequency-map (zipmap (range 100 130) (range 300))]
(word-cloud frequency-map
{:background {:type :circle :size 300}
:filename "sample.png" :font-y 100 :padding 10}))
(ns examples
(:require '[clj-wordcloud.core :refer :all]))
(let [frequency-map (zipmap (random-words 100) (shuffle (range 300)))
word-cloud (word-cloud frequency-map
{:dimension {:width 600
:height 600}
:background {:type :circle
:size 300
:color "0x000000"}
:font {:type "Calibre"
:weight :plain
:scale-type :linear
:x-scale 20
:y-scale 20
:padding 5}})]
(write-to-file word-cloud "example_circle.png"))
```
![Sample](/examples/sample.png)
![Sample](/examples/example_circle.png)
### Bitmaps
```clojure
(ns examples
(:require '[clj-wordcloud.core :refer :all]))
(let [frequency-map (zipmap (range 100 150) (shuffle (range 300)))
word-cloud (word-cloud frequency-map
{:dimension {:width 600
:height 600}
:background {:type :pixel
:size 300
:color "0x000000"
:bitmap "examples/backgrounds/haskell_1.bmp"}
:font {:type "Calibre"
:weight :plain
:scale-type :linear
:x-scale 20
:y-scale 20
:padding 5}})]
(write-to-file word-cloud "example_haskell.png"))
```
![Sample](/examples/example_haskell.png)
## TODO
* API parity with Kumo
* clojure.spec for docs and validation
* Cool examples
* Better tests
## Contributing
Contributions are welcome. Please refer to CONTRIBUTING.md.
## Stability
This library is still in early development phase and the API is subject to change.
This library is still in early development phase and the API is subject to change. API design comments are welcome.
## Thanks

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

BIN
examples/example_circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,7 +1,47 @@
(ns examples
(:require '[clj-wordcloud.core :refer :all]))
(let [frequency-map (zipmap (range 100 130) (range 300))]
(word-cloud frequency-map
{:background {:type :circle :size 300}
:filename "sample.png" :font-y 100 :padding 10}))
(defn random-words
[n]
(->> "/usr/share/dict/words"
slurp
clojure.string/lower-case
clojure.string/split-lines
shuffle
(take n)))
(let [frequency-map (zipmap (random-words 100) (shuffle (range 300)))
word-cloud (word-cloud frequency-map
{:dimension {:width 600
:height 600}
:background {:type :circle
:size 300
:color "0x000000"}
:font {:type "Calibre"
:weight :plain
:scale-type :linear
:x-scale 20
:y-scale 20
:padding 5}})]
(write-to-file word-cloud "example_circle.png"))
(let [frequency-map (zipmap (range 100 150) (shuffle (range 300)))
word-cloud (word-cloud frequency-map
{:dimension {:width 600
:height 600}
:background {:type :pixel
:size 300
:color "0x000000"
:bitmap "examples/backgrounds/haskell_1.bmp"}
:font {:type "Calibre"
:weight :plain
:scale-type :linear
:x-scale 20
:y-scale 20
:padding 5
:colors ["0x00FF00" "0x0000FF" "0xFFAFFF"
"0xFFEEFF" "0xEEEEEE"]}})]
(write-to-file word-cloud "example_haskell.png"))

View file

@ -1,4 +1,4 @@
(defproject xtreak/clj-wordcloud "0.1.0-SNAPSHOT"
(defproject xtreak/clj-wordcloud "0.0.1-SNAPSHOT"
:description "A simple clojure wrapper around kumo for wordcloud generation"
:url "http://github.com/tirkarthi/clj-wordcloud"
:license {:name "MIT public license"

View file

@ -1,21 +1,29 @@
(ns clj-wordcloud.core
(:import (com.kennycason.kumo WordCloud WordFrequency)
(java.awt Dimension)
(com.kennycason.kumo WordCloud WordFrequency CollisionMode)
(com.kennycason.kumo.bg CircleBackground RectangleBackground)
(:import (java.awt Dimension Color)
(java.awt.image BufferedImage)
(javax.imageio ImageIO)
(com.kennycason.kumo WordCloud WordFrequency LayeredWordCloud CollisionMode)
(com.kennycason.kumo.bg CircleBackground RectangleBackground PixelBoundryBackground
PixelBoundryBackground)
(com.kennycason.kumo.palette ColorPalette)
(com.kennycason.kumo.font KumoFont FontWeight)
(com.kennycason.kumo.font.scale LinearFontScalar)
(com.kennycason.kumo.nlp FrequencyAnalyzer)))
(defn- background-object
[options dimension]
(let [type (get-in options [:background :type] :circle)
size (get-in options [:background :size] 20)]
(let [type (get-in options [:background :type] :circle)
size (get-in options [:background :size] 20)
bitmap (get-in options [:background :bitmap])]
(case type
:circle
(CircleBackground. size)
:rectangle
(RectangleBackground. dimension))))
(RectangleBackground. dimension)
:pixel
(PixelBoundryBackground. (clojure.java.io/input-stream bitmap))
(CircleBackground. size))))
(defn- build-word-frequency
@ -25,16 +33,79 @@
(.add %1 (WordFrequency. (str word) count))))))
(defn- build-font-scalar
[options]
(let [scale-type (get-in options [:font :scale-type] :linear)
x-scale (get-in options [:font :x-scale] 10)
y-scale (get-in options [:font :y-scale] 10)]
(case scale-type
:linear
(LinearFontScalar. x-scale y-scale))))
(defn- build-font
[options]
(let [font-map {:plain FontWeight/PLAIN, :bold FontWeight/BOLD, :italic FontWeight/ITALIC}
font-type (get-in options [:font :type] "Arial")
font-weight (get-in options [:font :weight] :plain)]
(KumoFont. font-type (get font-map font-weight FontWeight/PLAIN))))
(defn- build-dimension
[options]
(let [width (get-in options [:dimension :width] 100)
height (get-in options [:dimension :height] 100)]
(Dimension. width height)))
(defn- build-color-palette
[options]
(let [default-colors ["0xFFFF00" "0x008000" "0x0000FF"]
colors (->> default-colors
(concat (get-in options [:font :colors] []))
(take 5))
color-palette (map #(Color/decode %1) colors)]
(ColorPalette. color-palette)))
(defn write-to-file
"Writes the word cloud object as png image to the given location.
Supply file name with extension png like example.png"
[word-cloud filename]
(.writeToFile word-cloud filename))
(defn word-cloud
"
Takes a map of string and the score along with options to return a wordcloud object
Options spec as below :
{:dimension {:width 600 ; width of the image
:height 600} ; height of the image
:background {:type :circle ; type. Takes :circle, :pixel (bitmaps), :rectangle
:size 300 ; size of the circle
:color \"0x000000\"} ; Background color as hex
:font {:type \"Calibre\" ; Font type
:weight :plain ; Font weight. Takes :plain, :bold, :italic
:scale-type :linear ; linear for now
:x-scale 20 ; x scale of font
:y-scale 20 ; y scale of font
:padding 5}} ; padding between entries
"
[frequency-map options]
(let [word-frequencies (build-word-frequency frequency-map)
dimension (Dimension. (:width options 600) (:height options 600))
dimension (build-dimension options)
word-cloud (WordCloud. dimension CollisionMode/PIXEL_PERFECT)
background (background-object options dimension)
font (LinearFontScalar. (:font-x options 10) (:font-y options 40))]
font-scalar (build-font-scalar options)
kumo-font (build-font options)
color-palette (build-color-palette options)]
(doto word-cloud
(.setPadding (:padding options 10))
(.setPadding (get-in options [:font :padding] 10))
(.setBackgroundColor (Color/decode (get-in options [:background :color] "0x000000")))
(.setColorPalette color-palette)
(.setBackground background)
(.setFontScalar font)
(.build word-frequencies)
(.writeToFile (:filename options "test.png")))))
(.setFontScalar font-scalar)
(.setKumoFont kumo-font)
(.build word-frequencies))))

View file

@ -9,9 +9,22 @@
(let [image (javax.imageio.ImageIO/read r)]
[(.getWidth image) (.getHeight image)])))
(deftest image-dimensions-test
(testing "Test width and height of the generated image"
(let [word-cloud (word-cloud (zipmap (range 100 130) (range 300))
{:background {:type :circle :size 300}
:filename "sample.png" :font-y 100 :padding 10})]
(let [freq-map (zipmap (range 100 130) (range 300))
word-cloud (word-cloud freq-map
{:dimension {:width 600
:height 600}
:background {:type :circle
:size 300
:color "0x000000"}
:font {:type "Comic Sans MS"
:scale-type :linear
:x-scale 20
:y-scale 20
:padding 5
:colors ["0x00FF00" "0x0000FF" "0xFFAFFF"
"0xFFEEFF" "0xEEEEEE"]}})]
(write-to-file word-cloud "sample.png")
(is (= (get-size "sample.png") [600 600])))))