spark_pr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ae3c06cbc2f596478b629cbe0cb1633f69588ba
4
+ data.tar.gz: 74c01a3c6803ab55cd31525efe57ac7e698232d7
5
+ SHA512:
6
+ metadata.gz: b7409d7d0e046cb2a45b1396ea6339e4aaf56a231057df192a62680f0b022e399bcc73726bd3b53e992f18bc0aa069c5ebbcd3ba01000afb780325c50ba7ab43
7
+ data.tar.gz: 5085572f5d9a30797ddfb0abe294b26649403081516916379b46192e64ea88877b239e41eed635ffbc42bd3dbabe9036a5790e838fa507e0d4302828103198a9
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
11
+ test.png
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in spark_pr.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2005 Thomas Fuchs
2
+ http://mir.aculo.us/
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,55 @@
1
+ spark_pr is a Ruby class to generate sparkline graphs with PNG or ASCII output.
2
+
3
+ It only depends on zlib and generates PNGs with pure Ruby code.
4
+ The line-graph outputs antialised lines.
5
+
6
+ Example for PNG output:
7
+
8
+ File.open( 'test.png', 'wb' ) do |png|
9
+ png << Spark.plot( [47, 43, 24, 47, 16, 28, 38, 57, 50, 76,
10
+ 42, 20, 98, 34, 53, 1, 55, 74, 63, 38,
11
+ 31, 98, 89],
12
+ :has_min => true, :has_max => true, 'has_last' => 'true',
13
+ 'height' => '40', :step => 10, :normalize => 'logarithmic' )
14
+ end
15
+
16
+ Example ASCII output:
17
+
18
+ spark = Spark.new({:has_min => true, :has_max => true, :height => 14, :step => 4})
19
+ puts spark.smooth( [47, 43, 24, 47, 16, 28, 38, 57, 50, 76,
20
+ 42, 1, 98, 34, 53, 97, 55, 74, 63, 38,
21
+ 31, 98, 89] ).to_ascii
22
+
23
+ The PNG output can also be obtained in data: URI format convenient for web
24
+ use. If the Spark.data_uri is used, there is also a dependency on Base64,
25
+ which is a standard library just like Zlib
26
+
27
+ You can paste the output from:
28
+
29
+ Spark.data_uri( [47, 43, 24, 47, 16, 28, 38, 57, 50, 76,
30
+ 42, 20, 98, 34, 53, 1, 55, 74, 63, 38,
31
+ 31, 98, 89],
32
+ :has_min => true, :has_max => true, 'has_last' => 'true',
33
+ 'height' => '40', :step => 10, :normalize => 'logarithmic' )
34
+
35
+ into your browser's address and see the PNG directly.
36
+
37
+ Class based usage:
38
+
39
+ spark = Spark.new(:has_min => true, :has_max => true, 'has_last' => 'true',
40
+ 'height' => '40', :step => 10, :normalize => 'logarithmic' )
41
+ spark.smooth(data)
42
+
43
+ File.open( 'test.png', 'wb' ) do |png|
44
+ png << spark.png
45
+ end
46
+
47
+ img_src = spark.data_uri
48
+
49
+
50
+ The SparkCanvas class can also be used for other drawing operations,
51
+ it provides drawing canvas with alpha blending and some primitive graphics
52
+ operations and PNG output in just about 100 lines of Ruby code.
53
+
54
+ Pure Ruby sparklines are released under the terms of the MIT-LICENSE.
55
+ See the included MIT-LICENSE file for details.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/lib/spark_pr.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'spark_pr/version'
2
+ require 'spark_pr/spark'
3
+ require 'spark_pr/spark_canvas'
4
+
@@ -0,0 +1,117 @@
1
+ require 'base64'
2
+ require_relative 'spark_canvas'
3
+
4
+ class Spark
5
+ attr_accessor :opts, :png, :canvas
6
+
7
+ def initialize(options)
8
+ # process options
9
+ o = options.inject({}) do |o, (key, value)|
10
+ o[key.to_sym] = value ; o
11
+ end
12
+ [:height, :width, :step].each do |k|
13
+ o[k] = o[k].to_i if o.has_key?(k)
14
+ end
15
+ [:has_min, :has_max, :has_last].each do |k|
16
+ o[k] = (o[k] ? true : false) if o.has_key?(k)
17
+ end
18
+ o[:normalize] ||= :linear
19
+ o[:normalize] = o[:normalize].to_sym
20
+
21
+ self.opts = o
22
+ end
23
+
24
+ # normalize arr to contain values between 0..1 inclusive
25
+ def normalize( arr, type = :linear )
26
+ arr = arr.map{|v| Math.log(v) } if type == :logarithmic
27
+ adj, fac = arr.min, arr.max-arr.min
28
+ arr.map {|v| (v-adj).quo(fac) rescue 0 }
29
+ end
30
+
31
+ def smooth( results )
32
+ o = {
33
+ :step => 2,
34
+ :height => 14,
35
+ :has_min => false,
36
+ :has_max => false
37
+ }.merge(opts)
38
+
39
+ o[:width] ||= (results.size-1)*o[:step] + 5
40
+
41
+ c = SparkCanvas.new(o[:width], o[:height])
42
+
43
+ results = normalize(results, o[:normalize])
44
+ fac = c.height-5
45
+ i = -o[:step]
46
+ coords = results.map do |r|
47
+ [(i += o[:step])+2, c.height - 3 - r*fac ]
48
+ end
49
+
50
+ c.color = opts[:line_color] || [0xB0, 0xB0, 0xB0, 0xFF]
51
+ c.polyline coords
52
+
53
+ if o[:has_min]
54
+ min_pt = coords[results.index(results.min)]
55
+ c.color = [0x80, 0x80, 0x00, 0x70]
56
+ c.rectangle(min_pt[0]-2, min_pt[1]-2, min_pt[0]+2, min_pt[1]+2)
57
+ end
58
+
59
+ if o[:has_max]
60
+ max_pt = coords[results.index(results.max)]
61
+ c.color = [0x00, 0x80, 0x00, 0x70]
62
+ c.rectangle(max_pt[0]-2, max_pt[1]-2, max_pt[0]+2, max_pt[1]+2)
63
+ end
64
+
65
+ if o[:has_last]
66
+ c.color = [0xFF, 0x00, 0x00, 0x70]
67
+ c.rectangle(coords.last[0]-2, coords.last[1]-2, coords.last[0]+2, coords.last[1]+2)
68
+ end
69
+ self.png = c.to_png
70
+ self.canvas = c
71
+ end
72
+
73
+ def discrete( results )
74
+ o = {
75
+ :height => 14,
76
+ :upper => 0.5,
77
+ :has_min => false,
78
+ :has_max => false
79
+ }.merge(opts)
80
+
81
+ o[:width] ||= results.size*2-1
82
+
83
+ c = SparkCanvas.new(o[:width], o[:height])
84
+
85
+ results = normalize(results, o[:normalize])
86
+ fac = c.height-4
87
+
88
+ i = -2
89
+ results.each do |r|
90
+ p = c.height - 4 - r*fac
91
+ c.color = r < o[:upper] ? [0x66,0x66,0x66,0xFF] : [0xFF,0x00,0x00,0xFF]
92
+ c.line(i+=2, p, i, p+3)
93
+ end
94
+
95
+ self.png = c.to_png
96
+ self.canvas = c
97
+ end
98
+
99
+ def data_uri
100
+ %{data:image/png;base64,#{Base64.encode64(png).gsub("\n",'')}}
101
+ end
102
+
103
+ # convenience methods
104
+ def self.plot( results, options = {} )
105
+ spark = Spark.new(options)
106
+ type = opts.delete(:type) || :smooth
107
+ spark.send(type, results, o).to_png
108
+ end
109
+
110
+ def self.data_uri( results, options = {} )
111
+ spark = Spark.new(options)
112
+ type = spark.opts.delete(:type) || :smooth
113
+ spark.send(type, results )
114
+ spark.data_uri
115
+ end
116
+ end
117
+
@@ -0,0 +1,115 @@
1
+ # pure ruby sparklines module, generates PNG or ASCII
2
+ # contact thomas@fesch.at for questions
3
+ #
4
+ # strives to be somewhat compatible with sparklines lib by
5
+ # {Dan Nugent}[mailto:nugend@gmail.com] and {Geoffrey Grosenbach}[mailto:boss@topfunky.com]
6
+ #
7
+ # png creation based on http://www.whytheluckystiff.net/bumpspark/
8
+
9
+ require 'zlib'
10
+
11
+ class SparkCanvas
12
+
13
+ attr_accessor :color
14
+ attr_reader :width, :height
15
+
16
+ def initialize(width,height)
17
+ @canvas = []
18
+ @height = height
19
+ @width = width
20
+ height.times{ @canvas << [[0xFF,0xFF,0xFF]]*width }
21
+ @color = [0,0,0,0xFF] #RGBA
22
+ end
23
+
24
+ # alpha blends two colors, using the alpha given by c2
25
+ def blend(c1, c2)
26
+ (0..2).map{ |i| (c1[i]*(0xFF-c2[3]) + c2[i]*c2[3]) >> 8 }
27
+ end
28
+
29
+ # calculate a new alpha given a 0-0xFF intensity
30
+ def intensity(c,i)
31
+ [c[0],c[1],c[2],(c[3]*i) >> 8]
32
+ end
33
+
34
+ # calculate perceptive grayscale value
35
+ def grayscale(c)
36
+ (c[0]*0.3 + c[1]*0.59 + c[2]*0.11).to_i
37
+ end
38
+
39
+ def point(x,y,color = nil)
40
+ return if x<0 or y<0 or x>@width-1 or y>@height-1
41
+ @canvas[y][x] = blend(@canvas[y][x], color || @color)
42
+ end
43
+
44
+ def rectangle(x0, y0, x1, y1)
45
+ x0, y0, x1, y1 = x0.to_i, y0.to_i, x1.to_i, y1.to_i
46
+ x0, x1 = x1, x0 if x0 > x1
47
+ y0, y1 = y1, y0 if y0 > y1
48
+ x0.upto(x1) { |x| y0.upto(y1) { |y| point x, y } }
49
+ end
50
+
51
+ # draw an antialiased line
52
+ # google for "wu antialiasing"
53
+ def line(x0, y0, x1, y1)
54
+ # clean params
55
+ x0, y0, x1, y1 = x0.to_i, y0.to_i, x1.to_i, y1.to_i
56
+ y0, y1, x0, x1 = y1, y0, x1, x0 if y0>y1
57
+ sx = (dx = x1-x0) < 0 ? -1 : 1 ; dx *= sx ; dy = y1-y0
58
+
59
+ # special cases
60
+ x0.step(x1,sx) { |x| point x, y0 } and return if dy.zero?
61
+ y0.upto(y1) { |y| point x0, y } and return if dx.zero?
62
+ x0.step(x1,sx) { |x| point x, y0; y0 += 1 } and return if dx==dy
63
+
64
+ # main loops
65
+ point x0, y0
66
+
67
+ e_acc = 0
68
+ if dy > dx
69
+ e = (dx << 16) / dy
70
+ y0.upto(y1-1) do
71
+ e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xFFFF
72
+ x0 += sx if (e_acc <= e_acc_temp)
73
+ point x0, (y0 += 1), intensity(@color,(w=0xFF-(e_acc >> 8)))
74
+ point x0+sx, y0, intensity(@color,(0xFF-w))
75
+ end
76
+ point x1, y1
77
+ return
78
+ end
79
+
80
+ e = (dy << 16) / dx
81
+ x0.step(x1-sx,sx) do
82
+ e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xFFFF
83
+ y0 += 1 if (e_acc <= e_acc_temp)
84
+ point (x0 += sx), y0, intensity(@color,(w=0xFF-(e_acc >> 8)))
85
+ point x0, y0+1, intensity(@color,(0xFF-w))
86
+ end
87
+ point x1, y1
88
+ end
89
+
90
+ def polyline(arr)
91
+ (0...arr.size-1).each{ |i| line(arr[i][0], arr[i][1], arr[i+1][0], arr[i+1][1]) }
92
+ end
93
+
94
+ def to_png
95
+ header = [137, 80, 78, 71, 13, 10, 26, 10].pack("C*")
96
+ raw_data = @canvas.map { |row| [0] + row }.flatten.pack("C*")
97
+ ihdr_data = [@canvas.first.length,@canvas.length,8,2,0,0,0].pack("NNCCCCC")
98
+
99
+ header +
100
+ build_png_chunk("IHDR", ihdr_data) +
101
+ build_png_chunk("tRNS", ([ 0xFF ]*6).pack("C6")) +
102
+ build_png_chunk("IDAT", Zlib::Deflate.deflate(raw_data)) +
103
+ build_png_chunk("IEND", "")
104
+ end
105
+
106
+ def build_png_chunk(type,data)
107
+ to_check = type + data
108
+ [data.length].pack("N") + to_check + [Zlib.crc32(to_check)].pack("N")
109
+ end
110
+
111
+ def to_ascii
112
+ chr = %w(M O # + ; - .) << ' '
113
+ @canvas.map{ |r| r.map { |pt| chr[grayscale(pt) >> 5] }.join << "\n" }.join
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ module SparkPr
2
+ VERSION = "0.1.0"
3
+ end
data/spark_pr.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'spark_pr/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "spark_pr"
8
+ spec.version = SparkPr::VERSION
9
+ spec.authors = ["Thomas Fuchs", "Rob Biedenharn", "Lukas Eklund"]
10
+ spec.email = ["leklund@gmail.com"]
11
+
12
+ spec.summary = %q{Pure Ruby sparkline graph generator with PNG or ASCII output}
13
+ spec.description = %q{spark_pr is a Ruby class to generate sparkline graphs with PNG or ASCII output. It only depends on zlib and generates PNGs with pure Ruby code. The line-graph outputs antialised lines.}
14
+ spec.homepage = "https://github.com/leklund/spark_pr"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.10"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "minitest"
25
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spark_pr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Fuchs
8
+ - Rob Biedenharn
9
+ - Lukas Eklund
10
+ autorequire:
11
+ bindir: exe
12
+ cert_chain: []
13
+ date: 2016-03-30 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.10'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.10'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '10.0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '10.0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: minitest
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ description: spark_pr is a Ruby class to generate sparkline graphs with PNG or ASCII
58
+ output. It only depends on zlib and generates PNGs with pure Ruby code. The line-graph
59
+ outputs antialised lines.
60
+ email:
61
+ - leklund@gmail.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - ".gitignore"
67
+ - Gemfile
68
+ - MIT-LICENSE
69
+ - README
70
+ - Rakefile
71
+ - lib/spark_pr.rb
72
+ - lib/spark_pr/spark.rb
73
+ - lib/spark_pr/spark_canvas.rb
74
+ - lib/spark_pr/version.rb
75
+ - spark_pr.gemspec
76
+ homepage: https://github.com/leklund/spark_pr
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.4.6
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Pure Ruby sparkline graph generator with PNG or ASCII output
100
+ test_files: []