elrio 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a80ee82d7cdb243d0d7e440a1189f284a951257a
4
- data.tar.gz: 3d5e5d5f8f7f5095d627603002055dc2c3817f8e
3
+ metadata.gz: 95d67d95fdf9b0ef83011a8ef477540f9ed20bc3
4
+ data.tar.gz: 8537667e7c1a1e99bc61ae6158a76ae054558dd3
5
5
  SHA512:
6
- metadata.gz: e65300dd7bf244c69aea9e48f361c345056793cdf8ae9ec5c51b7489692a2a0bb39a562fee1e10d78a00829d537da4a72dae94719b64a55c1ae993483a664ff8
7
- data.tar.gz: ff40869a428d24ad6d534c170a16fd2ba6d380092f2e34e78bb930d5b802ddf8e665e2aa3bc942815440731d17c512df63439a43d64f3259f8040d847d1288b5
6
+ metadata.gz: c65d31c63dc3e276204b5f07dbcb8daef918c6c8cb33e54dfed0400bbfc9756103ee73b891fd88fbdbe70de55b8f8fc9883cdc8397530d8bc97bd0a9df9b9790
7
+ data.tar.gz: b7bf1ed3afbdcc0dab75981bcde8991f27f308197f10fa2c04d51d411f7226214e0f02d5e077ad1f2bd1e637555f66277bf7287909c656c79431c03e5c967724
@@ -1,6 +1,9 @@
1
- require "elrio/cli"
2
1
  require "elrio/cap_inset_detector"
2
+ require "elrio/cli"
3
3
  require "elrio/geometry"
4
4
  require "elrio/image_optimizer"
5
+ require "elrio/n_gram_generator"
6
+ require "elrio/pattern_detector"
7
+ require "elrio/point_size"
5
8
  require "elrio/runner"
6
9
  require "elrio/version"
@@ -1,37 +1,24 @@
1
1
  module Elrio
2
2
  class CapInsetDetector
3
- def detect_cap_insets(array)
4
- prev = array.first
5
- runs = [1]
6
-
7
- (1...array.count).each do |i|
8
- if array[i] == prev
9
- runs[-1] += 1
10
- else
11
- runs << 1
12
- end
13
-
14
- prev = array[i]
15
- end
16
-
17
- longest_run_length = runs.max
18
-
19
- return [array.count, 0] if longest_run_length == 1
20
-
21
- longest_run_index = runs.index(longest_run_length)
22
-
23
- if longest_run_index > 0
24
- run_start = runs[0, longest_run_index].reduce(:+)
25
- else
26
- run_start = 0
27
- end
28
-
29
- run_end = run_start + longest_run_length
3
+ def initialize(pattern_detector = PatternDetector.new)
4
+ @pattern_detector = pattern_detector
5
+ end
30
6
 
31
- [
32
- run_start,
33
- array.count - run_end
34
- ]
7
+ def detect_cap_insets(image)
8
+ columns = (0...image.width).map { |x| image.column(x) }
9
+ rows = (0...image.height).map { |y| image.row(y) }
10
+
11
+ horizontal_pattern = @pattern_detector.detect_pattern(columns)
12
+ vertical_pattern = @pattern_detector.detect_pattern(rows)
13
+
14
+ Insets.new(
15
+ vertical_pattern.start,
16
+ horizontal_pattern.start,
17
+ vertical_pattern.end,
18
+ horizontal_pattern.end,
19
+ horizontal_pattern.size,
20
+ vertical_pattern.size
21
+ )
35
22
  end
36
23
  end
37
24
  end
@@ -1,13 +1,36 @@
1
+ require "values"
2
+
1
3
  module Elrio
2
- Point = Struct.new(:x, :y)
4
+ Point = Value.new(:x, :y)
5
+
6
+ Size = Value.new(:width, :height)
3
7
 
4
- Size = Struct.new(:width, :height)
8
+ Rect = Value.new(:x, :y, :width, :height)
5
9
 
6
- Rect = Struct.new(:x, :y, :width, :height)
10
+ Pattern = Value.new(:start, :end, :size)
7
11
 
8
- Insets = Struct.new(:top, :left, :bottom, :right) do
12
+ class Insets < Value.new(:top, :left, :bottom, :right, :pattern_width, :pattern_height)
9
13
  def to_s
10
14
  [top, left, bottom, right].to_s
11
15
  end
16
+
17
+ def *(factor)
18
+ Insets.new(
19
+ (factor * top).ceil,
20
+ (factor * left).ceil,
21
+ (factor * bottom).ceil,
22
+ (factor * right).ceil,
23
+ pattern_width,
24
+ pattern_height
25
+ )
26
+ end
27
+
28
+ def /(factor)
29
+ self * (1.0 / factor)
30
+ end
31
+
32
+ def coerce(number)
33
+ [self, number]
34
+ end
12
35
  end
13
36
  end
@@ -1,73 +1,44 @@
1
1
  module Elrio
2
2
  class ImageOptimizer
3
- def initialize(retina = false)
4
- @retina = retina
5
- end
6
-
7
- def detect_cap_insets(image)
8
- insets = detect_cap_insets_in_pixels(image)
9
-
10
- if @retina
11
- Insets.new(
12
- (insets.top + 1) / 2,
13
- (insets.left + 1) / 2,
14
- (insets.bottom + 1) / 2,
15
- (insets.right + 1) / 2
16
- )
17
- else
18
- insets
19
- end
20
- end
21
-
22
- def optimize(image, insets)
23
- insets = insets.dup
24
- repeatable_size = 1
25
-
26
- if @retina
27
- repeatable_size *= 2
28
- insets.top *= 2
29
- insets.left *= 2
30
- insets.bottom *= 2
31
- insets.right *= 2
32
- end
33
-
34
- target_height = insets.top + insets.bottom + repeatable_size
35
- target_width = insets.left + insets.right + repeatable_size
3
+ def optimize(image, pixel_insets)
4
+ target = target_size(pixel_insets)
36
5
 
37
- return nil if target_height > image.height || target_width > image.width
6
+ return if target.height > image.height || target.width > image.width
38
7
 
39
- source_x = image.width - insets.right
40
- source_y = image.height - insets.bottom
41
- target_x = target_width - insets.right
42
- target_y = target_height - insets.bottom
8
+ source_x = image.width - pixel_insets.right
9
+ source_y = image.height - pixel_insets.bottom
10
+ target_x = target.width - pixel_insets.right
11
+ target_y = target.height - pixel_insets.bottom
12
+ source_width = pixel_insets.left + pixel_insets.pattern_width
13
+ source_height = pixel_insets.top + pixel_insets.pattern_height
43
14
 
44
- optimized = ChunkyPNG::Image.new(target_width, target_height)
15
+ optimized = ChunkyPNG::Image.new(target.width, target.height)
45
16
 
46
17
  copy_rect(
47
18
  image,
48
19
  optimized,
49
- Rect.new(0, 0, insets.left + repeatable_size, insets.top + repeatable_size),
20
+ Rect.new(0, 0, source_width, source_height),
50
21
  Point.new(0, 0)
51
22
  )
52
23
 
53
24
  copy_rect(
54
25
  image,
55
26
  optimized,
56
- Rect.new(source_x, 0, insets.right, insets.top + repeatable_size),
27
+ Rect.new(source_x, 0, pixel_insets.right, source_height),
57
28
  Point.new(target_x, 0)
58
29
  )
59
30
 
60
31
  copy_rect(
61
32
  image,
62
33
  optimized,
63
- Rect.new(0, source_y, insets.left + repeatable_size, insets.bottom),
34
+ Rect.new(0, source_y, source_width, pixel_insets.bottom),
64
35
  Point.new(0, target_y)
65
36
  )
66
37
 
67
38
  copy_rect(
68
39
  image,
69
40
  optimized,
70
- Rect.new(source_x, source_y, insets.right, insets.bottom),
41
+ Rect.new(source_x, source_y, pixel_insets.right, pixel_insets.bottom),
71
42
  Point.new(target_x, target_y)
72
43
  )
73
44
 
@@ -76,23 +47,6 @@ module Elrio
76
47
 
77
48
  private
78
49
 
79
- def detect_cap_insets_in_pixels(image)
80
- columns = (0...image.width).map {|x| image.column(x) }
81
- rows = (0...image.height).map {|y| image.row(y) }
82
-
83
- detector = CapInsetDetector.new
84
-
85
- column_info = detector.detect_cap_insets(columns)
86
- row_info = detector.detect_cap_insets(rows)
87
-
88
- Insets.new(
89
- row_info[0],
90
- column_info[0],
91
- row_info[1],
92
- column_info[1]
93
- )
94
- end
95
-
96
50
  def copy_rect(src, dest, src_rect, dest_origin)
97
51
  (0...src_rect.width).each do |x|
98
52
  (0...src_rect.height).each do |y|
@@ -106,5 +60,12 @@ module Elrio
106
60
  end
107
61
  end
108
62
  end
63
+
64
+ def target_size(insets)
65
+ height = insets.top + insets.bottom + insets.pattern_height
66
+ width = insets.left + insets.right + insets.pattern_width
67
+
68
+ Size.new(width, height)
69
+ end
109
70
  end
110
71
  end
@@ -0,0 +1,22 @@
1
+ module Elrio
2
+ class NGramGenerator
3
+ include Enumerable
4
+
5
+ def initialize(list, n = 1, offset = 0)
6
+ @offset = offset
7
+ @list = list
8
+ @n = n
9
+ end
10
+
11
+ def each
12
+ yield @list[0, @offset]
13
+
14
+ i = @offset
15
+
16
+ while i < @list.size
17
+ yield @list[i, @n]
18
+ i += @n
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,63 @@
1
+ module Elrio
2
+ class PatternDetector
3
+ def detect_pattern(array)
4
+ max_n = array.size / 2
5
+ longest_run = (0..0)
6
+ longest_run_n = 1
7
+
8
+ (1..max_n).each do |n|
9
+ max_offset = [n-1, array.size - 2*n].min
10
+
11
+ (0..max_offset).each do |offset|
12
+ generator = NGramGenerator.new(array, n, offset)
13
+ run = find_longest_run(generator)
14
+
15
+ if run.size > [n, longest_run.size].max
16
+ longest_run = run
17
+ longest_run_n = n
18
+ end
19
+ end
20
+ end
21
+
22
+ if longest_run.size == 1
23
+ start_cap = array.size
24
+ end_cap = 0
25
+ else
26
+ start_cap = longest_run.first
27
+ end_cap = array.count - longest_run.last - 1
28
+ end
29
+
30
+ Pattern.new(start_cap, end_cap, longest_run_n)
31
+ end
32
+
33
+ private
34
+
35
+ def find_longest_run(generator)
36
+ prev = nil
37
+ runs = []
38
+
39
+ generator.each do |ngram|
40
+ if ngram == prev
41
+ runs[-1] += ngram.size
42
+ else
43
+ runs << ngram.size
44
+ end
45
+
46
+ prev = ngram
47
+ end
48
+
49
+ longest_run_length = runs.max
50
+ longest_run_index = runs.index(longest_run_length)
51
+
52
+ if longest_run_index > 0
53
+ run_start = runs[0, longest_run_index].reduce(:+)
54
+ else
55
+ run_start = 0
56
+ end
57
+
58
+ run_end = run_start + longest_run_length - 1
59
+
60
+ (run_start..run_end)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,7 @@
1
+ module Elrio
2
+ class PointSize
3
+ def self.from_filename(filename)
4
+ filename =~ /@2x/ ? 2 : 1
5
+ end
6
+ end
7
+ end
@@ -2,43 +2,41 @@ require "chunky_png"
2
2
 
3
3
  module Elrio
4
4
  class Runner
5
+ def initialize(cap_inset_detector = CapInsetDetector.new, image_optimizer = ImageOptimizer.new)
6
+ @cap_inset_detector = cap_inset_detector
7
+ @image_optimizer = image_optimizer
8
+ end
9
+
5
10
  def analyze(path)
6
11
  image = ChunkyPNG::Image.from_file(path)
7
- image_optimizer = ImageOptimizer.new(is_retina?(path))
8
- image_optimizer.detect_cap_insets(image)
12
+ scale = PointSize.from_filename(path)
13
+ insets = @cap_inset_detector.detect_cap_insets(image)
14
+ insets / scale
9
15
  end
10
16
 
11
17
  def optimize(path)
12
- retina = is_retina?(path)
13
-
14
- if retina
15
- opt_suffix = "-optimized@2x.png"
16
- opt_base = path.sub(/@2x/, '')
17
- else
18
- opt_suffix = "-optimized.png"
19
- opt_base = path
20
- end
21
-
22
- optimized_path = File.join(
23
- File.dirname(opt_base),
24
- File.basename(opt_base, ".*") + opt_suffix
25
- )
26
-
27
18
  image = ChunkyPNG::Image.from_file(path)
19
+ scale = PointSize.from_filename(path)
20
+ insets = @cap_inset_detector.detect_cap_insets(image)
21
+ point_insets = insets / scale
28
22
 
29
- image_optimizer = ImageOptimizer.new(retina)
30
- insets = image_optimizer.detect_cap_insets(image)
23
+ optimized_image = @image_optimizer.optimize(image, insets)
31
24
 
32
- optimized = image_optimizer.optimize(image, insets)
33
- optimized.save(optimized_path) if optimized
25
+ if optimized_image
26
+ optimized_path = optimized_path_for(path)
27
+ optimized_image.save(optimized_path)
28
+ end
34
29
 
35
- insets
30
+ point_insets
36
31
  end
37
32
 
38
33
  private
39
34
 
40
- def is_retina?(path)
41
- !!(path =~ /@2x/)
35
+ def optimized_path_for(path)
36
+ File.join(
37
+ File.dirname(path),
38
+ File.basename(path, ".*") + "-optimized.png"
39
+ )
42
40
  end
43
41
  end
44
42
  end
@@ -1,3 +1,3 @@
1
1
  module Elrio
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elrio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Can Berk Güder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-11 00:00:00.000000000 Z
11
+ date: 2014-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: values
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description: Cap inset detector & optimizer for resizable UIKit assets.
70
84
  email:
71
85
  - cbguder@gmail.com
@@ -74,33 +88,17 @@ executables:
74
88
  extensions: []
75
89
  extra_rdoc_files: []
76
90
  files:
77
- - .gitignore
78
- - .rspec
79
- - .ruby-gemset
80
- - .ruby-version
81
- - .travis.yml
82
- - Gemfile
83
- - Gemfile.lock
84
- - LICENSE.txt
85
- - README.md
86
- - Rakefile
87
91
  - bin/elrio
88
- - elrio.gemspec
89
92
  - lib/elrio.rb
90
93
  - lib/elrio/cap_inset_detector.rb
91
94
  - lib/elrio/cli.rb
92
95
  - lib/elrio/geometry.rb
93
96
  - lib/elrio/image_optimizer.rb
97
+ - lib/elrio/n_gram_generator.rb
98
+ - lib/elrio/pattern_detector.rb
99
+ - lib/elrio/point_size.rb
94
100
  - lib/elrio/runner.rb
95
101
  - lib/elrio/version.rb
96
- - spec/elrio/cap_inset_detector_spec.rb
97
- - spec/elrio/cli_spec.rb
98
- - spec/elrio/image_optimizer_spec.rb
99
- - spec/elrio/runner_spec.rb
100
- - spec/fixtures/optimized.png
101
- - spec/fixtures/optimized@2x.png
102
- - spec/fixtures/original.png
103
- - spec/spec_helper.rb
104
102
  homepage: https://github.com/cbguder/elrio
105
103
  licenses:
106
104
  - MIT
@@ -121,16 +119,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
119
  version: '0'
122
120
  requirements: []
123
121
  rubyforge_project:
124
- rubygems_version: 2.0.6
122
+ rubygems_version: 2.2.2
125
123
  signing_key:
126
124
  specification_version: 4
127
125
  summary: Cap inset detector & optimizer for resizable UIKit assets.
128
- test_files:
129
- - spec/elrio/cap_inset_detector_spec.rb
130
- - spec/elrio/cli_spec.rb
131
- - spec/elrio/image_optimizer_spec.rb
132
- - spec/elrio/runner_spec.rb
133
- - spec/fixtures/optimized.png
134
- - spec/fixtures/optimized@2x.png
135
- - spec/fixtures/original.png
136
- - spec/spec_helper.rb
126
+ test_files: []
data/.gitignore DELETED
@@ -1,16 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- InstalledFiles
7
- _yardoc
8
- coverage
9
- doc/
10
- lib/bundler/man
11
- pkg
12
- rdoc
13
- spec/reports
14
- test/tmp
15
- test/version_tmp
16
- tmp
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --format progress
@@ -1 +0,0 @@
1
- elrio
@@ -1 +0,0 @@
1
- ruby-2.0.0-p247
@@ -1,3 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.0.0
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
@@ -1,29 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- elrio (0.0.1)
5
- chunky_png
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- chunky_png (1.2.8)
11
- diff-lcs (1.2.4)
12
- rake (0.9.6)
13
- rspec (2.14.1)
14
- rspec-core (~> 2.14.0)
15
- rspec-expectations (~> 2.14.0)
16
- rspec-mocks (~> 2.14.0)
17
- rspec-core (2.14.5)
18
- rspec-expectations (2.14.2)
19
- diff-lcs (>= 1.1.3, < 2.0)
20
- rspec-mocks (2.14.3)
21
-
22
- PLATFORMS
23
- ruby
24
-
25
- DEPENDENCIES
26
- bundler (~> 1.3)
27
- elrio!
28
- rake
29
- rspec
@@ -1,22 +0,0 @@
1
- Copyright (c) 2013 Can Berk Güder
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md DELETED
@@ -1,51 +0,0 @@
1
- # Elrio
2
-
3
- Cap inset detector & optimizer for resizable UIKit assets.
4
-
5
- [![Code Climate](https://codeclimate.com/github/cbguder/elrio.png)](https://codeclimate.com/github/cbguder/elrio)
6
- [![Build Status](https://travis-ci.org/cbguder/elrio.png)](https://travis-ci.org/cbguder/elrio)
7
-
8
- ## Installation
9
-
10
- Add this line to your application's Gemfile:
11
-
12
- gem 'elrio'
13
-
14
- And then execute:
15
-
16
- $ bundle
17
-
18
- Or install it yourself as:
19
-
20
- $ gem install elrio
21
-
22
- ## Usage
23
-
24
- To get the resizable cap insets for an asset:
25
-
26
- $ elrio analyze image.png
27
-
28
- To create an optimized version of the asset:
29
-
30
- $ elrio optimize image.png
31
-
32
- ## Example
33
-
34
- When run with this image:
35
-
36
- ![Source Image](https://raw.github.com/cbguder/elrio/master/spec/fixtures/original.png)
37
-
38
- $ elrio optimize image.png
39
- image.png: [48, 48, 48, 48] # Top, Left, Bottom, Right
40
-
41
- This optimized version is written to `image-optimized.png`:
42
-
43
- ![Source Image](https://raw.github.com/cbguder/elrio/master/spec/fixtures/optimized.png)
44
-
45
- ## Contributing
46
-
47
- 1. Fork it
48
- 2. Create your feature branch (`git checkout -b my-new-feature`)
49
- 3. Commit your changes (`git commit -am 'Add some feature'`)
50
- 4. Push to the branch (`git push origin my-new-feature`)
51
- 5. Create new Pull Request
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
@@ -1,27 +0,0 @@
1
- # coding: utf-8
2
-
3
- lib = File.expand_path("../lib", __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require "elrio/version"
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = "elrio"
9
- spec.version = Elrio::VERSION
10
- spec.authors = ["Can Berk Güder"]
11
- spec.email = ["cbguder@gmail.com"]
12
- spec.description = "Cap inset detector & optimizer for resizable UIKit assets."
13
- spec.summary = "Cap inset detector & optimizer for resizable UIKit assets."
14
- spec.homepage = "https://github.com/cbguder/elrio"
15
- spec.license = "MIT"
16
-
17
- spec.files = `git ls-files`.split($/)
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_development_dependency "bundler", "~> 1.3"
23
- spec.add_development_dependency "rake"
24
- spec.add_development_dependency "rspec"
25
-
26
- spec.add_runtime_dependency "chunky_png"
27
- end
@@ -1,40 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Elrio::CapInsetDetector do
4
- describe "#detect_cap_insets" do
5
- it "returns the non-repeating prefix and suffix lengths of a collection" do
6
- data = %w(A - - - B C)
7
- subject.detect_cap_insets(data).should == [1, 2]
8
- end
9
-
10
- it "returns zero when all items are the same" do
11
- data = %w(- - -)
12
- subject.detect_cap_insets(data).should == [0, 0]
13
- end
14
-
15
- it "returns the length of the collection when all items are unique" do
16
- data = %w(A B C D E)
17
- subject.detect_cap_insets(data).should == [5, 0]
18
- end
19
-
20
- it "does not fail with a single-item collection" do
21
- data = %w(A)
22
- subject.detect_cap_insets(data).should == [1, 0]
23
- end
24
-
25
- it "can handle multiple runs" do
26
- data = %w(A A A B C - - - - - D E F F F)
27
- subject.detect_cap_insets(data).should == [5, 5]
28
- end
29
-
30
- it "can handle longest runs at the beginning" do
31
- data = %w(- - - A)
32
- subject.detect_cap_insets(data).should == [0, 1]
33
- end
34
-
35
- it "can handle longest runs at the end" do
36
- data = %w(A - - -)
37
- subject.detect_cap_insets(data).should == [1, 0]
38
- end
39
- end
40
- end
@@ -1,56 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Elrio::CLI do
4
- let(:output) { double(:output) }
5
-
6
- subject { Elrio::CLI.new(output) }
7
-
8
- describe "#run" do
9
- let(:runner) { double(Elrio::Runner) }
10
-
11
- before do
12
- Elrio::Runner.stub(:new).and_return(runner)
13
- end
14
-
15
- context "when run without a command" do
16
- it "prints usage instructions" do
17
- output.should_receive(:puts).with(/Usage: elrio <command> <images>/)
18
- subject.run([])
19
- end
20
- end
21
-
22
- context "when run with the analyze command" do
23
- before do
24
- runner.stub(:analyze).and_return(Elrio::Insets.new(1, 2, 3, 4))
25
- end
26
-
27
- it "prints the cap insets for each file" do
28
- args = %w(analyze foo bar)
29
-
30
- args[1..-1].each do |arg|
31
- runner.should_receive(:analyze).with(arg)
32
- output.should_receive(:puts).with("#{arg}: [1, 2, 3, 4]")
33
- end
34
-
35
- subject.run(args)
36
- end
37
- end
38
-
39
- context "when run with the optimize command" do
40
- before do
41
- runner.stub(:optimize).and_return(Elrio::Insets.new(1, 2, 3, 4))
42
- end
43
-
44
- it "prints the cap insets for each file" do
45
- args = %w(optimize foo bar)
46
-
47
- args[1..-1].each do |arg|
48
- runner.should_receive(:optimize).with(arg)
49
- output.should_receive(:puts).with("#{arg}: [1, 2, 3, 4]")
50
- end
51
-
52
- subject.run(args)
53
- end
54
- end
55
- end
56
- end
@@ -1,82 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Elrio::ImageOptimizer do
4
- describe "#detect_cap_insets" do
5
- let(:cap_inset_detector) { double(Elrio::CapInsetDetector) }
6
- let(:image) { double(ChunkyPNG::Image) }
7
- let(:columns) { [double] * 5 }
8
- let(:rows) { [double] * 3 }
9
-
10
- before do
11
- image.stub(:width).and_return(columns.count)
12
- image.stub(:height).and_return(rows.count)
13
- image.stub(:column) {|x| columns[x] }
14
- image.stub(:row) {|x| rows[x] }
15
-
16
- cap_inset_detector.stub(:detect_cap_insets).with(rows).and_return([1, 3])
17
- cap_inset_detector.stub(:detect_cap_insets).with(columns).and_return([2, 4])
18
-
19
- Elrio::CapInsetDetector.stub(:new).and_return(cap_inset_detector)
20
- end
21
-
22
- context "in non-retina mode" do
23
- it "passes the rows and columns to the detector" do
24
- subject.detect_cap_insets(image).should == Elrio::Insets.new(1, 2, 3, 4)
25
- end
26
- end
27
-
28
- context "in retina mode" do
29
- subject { Elrio::ImageOptimizer.new(true) }
30
-
31
- it "halves the cap insets" do
32
- subject.detect_cap_insets(image).should == Elrio::Insets.new(1, 1, 2, 2)
33
- end
34
- end
35
- end
36
-
37
- describe "#optimize" do
38
- let(:image) { ChunkyPNG::Image.from_file("spec/fixtures/original.png") }
39
-
40
- context "in non-retina mode" do
41
- let(:expected) { ChunkyPNG::Image.from_file("spec/fixtures/optimized.png") }
42
-
43
- it "produces the expected image" do
44
- optimized = subject.optimize(image, Elrio::Insets.new(48, 48, 48, 48))
45
- optimized.should == expected
46
- end
47
-
48
- it "does not modify the insets" do
49
- insets = Elrio::Insets.new(48, 48, 48, 48)
50
- subject.optimize(image, insets)
51
- insets.should == Elrio::Insets.new(48, 48, 48, 48)
52
- end
53
-
54
- it "returns nil if insets are too big" do
55
- optimized = subject.optimize(image, Elrio::Insets.new(image.height, image.width, 0, 0))
56
- optimized.should be_nil
57
- end
58
- end
59
-
60
- context "in retina mode" do
61
- let(:expected) { ChunkyPNG::Image.from_file("spec/fixtures/optimized@2x.png") }
62
-
63
- subject { Elrio::ImageOptimizer.new(true) }
64
-
65
- it "produces the expected image" do
66
- optimized = subject.optimize(image, Elrio::Insets.new(24, 24, 24, 24))
67
- optimized.should == expected
68
- end
69
-
70
- it "does not modify the insets" do
71
- insets = Elrio::Insets.new(24, 24, 24, 24)
72
- subject.optimize(image, insets)
73
- insets.should == Elrio::Insets.new(24, 24, 24, 24)
74
- end
75
-
76
- it "returns nil if insets are too big" do
77
- optimized = subject.optimize(image, Elrio::Insets.new(image.height / 2, image.width / 2, 0, 0))
78
- optimized.should be_nil
79
- end
80
- end
81
- end
82
- end
@@ -1,86 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Elrio::Runner do
4
- let(:image) { double(ChunkyPNG::Image) }
5
- let(:optimized) { double(ChunkyPNG::Image) }
6
- let(:image_optimizer) { double(Elrio::ImageOptimizer) }
7
- let(:insets) { double(Elrio::Insets) }
8
-
9
- before do
10
- ChunkyPNG::Image.stub(:from_file).with(path).and_return(image)
11
- image_optimizer.stub(:detect_cap_insets).and_return(insets)
12
- end
13
-
14
- describe "#analyze" do
15
- context "with a non-retina image" do
16
- let(:path) { "file/path.png".freeze }
17
-
18
- before do
19
- Elrio::ImageOptimizer.should_receive(:new).with(false).and_return(image_optimizer)
20
- end
21
-
22
- it "returns the cap insets detected by the optimizer" do
23
- subject.analyze(path).should == insets
24
- end
25
- end
26
-
27
- context "with a retina image" do
28
- let(:path) { "file/path@2x.png".freeze }
29
-
30
- before do
31
- Elrio::ImageOptimizer.should_receive(:new).with(true).and_return(image_optimizer)
32
- end
33
-
34
- it "returns the cap insets detected by the optimizer" do
35
- subject.analyze(path).should == insets
36
- end
37
- end
38
- end
39
-
40
- describe "#optimize" do
41
- context "when the image is optimizable" do
42
- before do
43
- image_optimizer.stub(:optimize).with(image, insets).and_return(optimized)
44
- end
45
-
46
- context "with a non-retina image" do
47
- let(:path) { "file/path.png".freeze }
48
-
49
- before do
50
- Elrio::ImageOptimizer.should_receive(:new).with(false).and_return(image_optimizer)
51
- optimized.should_receive(:save).with("file/path-optimized.png")
52
- end
53
-
54
- it "returns the cap insets detected by the optimizer" do
55
- subject.optimize(path).should == insets
56
- end
57
- end
58
-
59
- context "with a retina image" do
60
- let(:path) { "file/path@2x.png".freeze }
61
-
62
- before do
63
- Elrio::ImageOptimizer.should_receive(:new).with(true).and_return(image_optimizer)
64
- optimized.should_receive(:save).with("file/path-optimized@2x.png")
65
- end
66
-
67
- it "returns the cap insets detected by the optimizer" do
68
- subject.optimize(path).should == insets
69
- end
70
- end
71
- end
72
-
73
- context "when the image is not optimizable" do
74
- let(:path) { "file/path.png".freeze }
75
-
76
- before do
77
- Elrio::ImageOptimizer.should_receive(:new).and_return(image_optimizer)
78
- image_optimizer.stub(:optimize).with(image, insets).and_return(nil)
79
- end
80
-
81
- it "does not blow up" do
82
- -> { subject.optimize(path) }.should_not raise_exception
83
- end
84
- end
85
- end
86
- end
Binary file
Binary file
@@ -1,5 +0,0 @@
1
- require "elrio"
2
-
3
- RSpec.configure do |config|
4
- config.order = "random"
5
- end