svg_profiler 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -4,10 +4,8 @@ Profiles a Scalable Vector Graphics xml string.
4
4
 
5
5
  ## Setup
6
6
 
7
- SVG Profiler depends on an open-source application called Inkscape.
8
-
9
7
  ```
10
- brew install inkscape
8
+ brew install imagemagick inkscape
11
9
  gem install svg_profiler
12
10
  ```
13
11
 
@@ -29,8 +27,23 @@ profile.height
29
27
 
30
28
  profile.aspect
31
29
  #=> 1.5
30
+
31
+ # The #colors method calculates the histogram for the SVG.
32
+ profile.colors
33
+ #=> { "#FF0000" => 0.7, "#FFFFFF" => 0.29, "#000000" => 0.01 }
34
+ ```
35
+
36
+ You may find that the SVG is [antialiased](http://en.wikipedia.org/wiki/Spatial_anti-aliasing) before the histogram is calculated.
37
+
38
+ You can pass an optional threshold to the `#colors` method, to help cope with this:
39
+
40
+ ```ruby
41
+ profile.colors(0.02)
42
+ #=> { "#FF0000" => 0.7070707070707071, "#FFFFFF" => 0.29292929292929293 }
32
43
  ```
33
44
 
45
+ The sum of the values in the hash will always add up to one.
46
+
34
47
  ## Contribution
35
48
 
36
49
  If there's a metric you'd like to see implemented, please send a pull request or open an issue.
@@ -1,4 +1,7 @@
1
1
  require "tempfile"
2
2
 
3
+ require "rmagick"
4
+
3
5
  require "svg_profiler/base"
4
6
  require "svg_profiler/inkscape"
7
+ require "svg_profiler/histogram"
@@ -20,4 +20,8 @@ class SVGProfiler
20
20
  width.to_f / height
21
21
  end
22
22
 
23
+ def colors(threshold = 0)
24
+ @inkscape.yield_png { |png| Histogram.for(png, threshold) }
25
+ end
26
+
23
27
  end
@@ -0,0 +1,48 @@
1
+ class SVGProfiler::Histogram
2
+
3
+ def self.for(png, threshold)
4
+ new(png).histogram(threshold)
5
+ end
6
+
7
+ def initialize(png)
8
+ check_for_imagemagick
9
+ @image = Magick::Image.read(png.path).first
10
+ end
11
+
12
+ def histogram(threshold)
13
+ @image.quantize(8) # 00-FF is 8-bits.
14
+
15
+ histogram = @image.color_histogram
16
+ frequencies = histogram.inject({}) do |hash, (p, f)|
17
+ hash.merge(to_hex(p) => f)
18
+ end
19
+
20
+ ratios = normalize(frequencies)
21
+ ratios.reject! { |_, v| v < threshold }
22
+
23
+ # Re-normalize after thresholding.
24
+ normalize(ratios)
25
+ end
26
+
27
+ private
28
+ def check_for_imagemagick
29
+ unless system("which convert &>/dev/null")
30
+ raise DependencyError.new(
31
+ "Could not locate Imagemagick, try `brew install imagemagick'"
32
+ )
33
+ end
34
+ end
35
+
36
+ def to_hex(pixel)
37
+ # The first two parameters are ignored by RMagick.
38
+ pixel.to_color(Magick::AllCompliance, false, 8, true)
39
+ end
40
+
41
+ def normalize(frequencies)
42
+ sum = frequencies.values.inject(:+)
43
+ frequencies.inject({}) do |hash, (k, v)|
44
+ hash.merge(k => v.to_f / sum)
45
+ end
46
+ end
47
+
48
+ end
@@ -2,11 +2,7 @@ class SVGProfiler::Inkscape
2
2
 
3
3
  def initialize(xml)
4
4
  check_for_inkscape
5
-
6
- input = Tempfile.new(["input", ".svg"])
7
- input.write(xml.to_s)
8
- input.close
9
- @path = input.path
5
+ @xml = xml
10
6
  end
11
7
 
12
8
  def width
@@ -17,6 +13,15 @@ class SVGProfiler::Inkscape
17
13
  exec("-H").to_i
18
14
  end
19
15
 
16
+ def yield_png(&block)
17
+ tmp = Tempfile.new(["tmp", ".png"])
18
+ write_png(tmp.path)
19
+ yield tmp
20
+ ensure
21
+ tmp.close
22
+ tmp.unlink
23
+ end
24
+
20
25
  private
21
26
  def check_for_inkscape
22
27
  unless system("which inkscape &>/dev/null")
@@ -27,7 +32,17 @@ class SVGProfiler::Inkscape
27
32
  end
28
33
 
29
34
  def exec(command)
30
- `inkscape -z #{command} #@path`
35
+ input = Tempfile.new(["input", ".svg"])
36
+ input.write(@xml.to_s)
37
+ input.close
38
+
39
+ `inkscape -z #{command} #{input.path}`
40
+ ensure
41
+ input.unlink
42
+ end
43
+
44
+ def write_png(path)
45
+ exec("-e #{path}")
31
46
  end
32
47
 
33
48
  class DependencyError < StandardError; end
metadata CHANGED
@@ -1,83 +1,82 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: svg_profiler
3
- version: !ruby/object:Gem::Version
4
- hash: 21
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 1
10
- version: 1.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Chris Patuzzo
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2013-03-09 00:00:00 +00:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: rspec
12
+ date: 2013-03-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rmagick
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
23
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
25
33
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
33
38
  type: :development
34
- version_requirements: *id001
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
35
46
  description: Profiles a Scalable Vector Graphics xml string.
36
47
  email: chris@patuzzo.co.uk
37
48
  executables: []
38
-
39
49
  extensions: []
40
-
41
50
  extra_rdoc_files: []
42
-
43
- files:
51
+ files:
44
52
  - README.md
45
53
  - lib/svg_profiler/base.rb
54
+ - lib/svg_profiler/histogram.rb
46
55
  - lib/svg_profiler/inkscape.rb
47
56
  - lib/svg_profiler.rb
48
- has_rdoc: true
49
57
  homepage: https://github.com/cpatuzzo/svg_profiler
50
58
  licenses: []
51
-
52
59
  post_install_message:
53
60
  rdoc_options: []
54
-
55
- require_paths:
61
+ require_paths:
56
62
  - lib
57
- required_ruby_version: !ruby/object:Gem::Requirement
63
+ required_ruby_version: !ruby/object:Gem::Requirement
58
64
  none: false
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- hash: 3
63
- segments:
64
- - 0
65
- version: "0"
66
- required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
70
  none: false
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- hash: 3
72
- segments:
73
- - 0
74
- version: "0"
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
75
  requirements: []
76
-
77
76
  rubyforge_project:
78
- rubygems_version: 1.6.2
77
+ rubygems_version: 1.8.23
79
78
  signing_key:
80
79
  specification_version: 3
81
80
  summary: SVG Profiler
82
81
  test_files: []
83
-
82
+ has_rdoc: