camalian 0.1.1 → 0.2.0

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
  SHA256:
3
- metadata.gz: 01c8d4bae81e85284d554a538c52e90741f0db58ddba1d6d9e921761cf041d91
4
- data.tar.gz: c5a301ed8505a08e31ed1c65cc4e5c8b0b1ccc832fad6e8279cb279f4750dadd
3
+ metadata.gz: d6d9583383ecf60a0cd259bcce471abe319f2b4390b52c53d63a2504f3dd020f
4
+ data.tar.gz: 6e5cb3a2c174539b91bae01fafad0e9ef658756bebc7809837cc0edb019cfacd
5
5
  SHA512:
6
- metadata.gz: '0418f17dfb07d45db856e30e9b333b532be7a38045aa4be3aae32192e62de4c803837a6730df08a797f3c662bd9a3fc0f21a5e780edfcf8545b3c085440af2d0'
7
- data.tar.gz: 0e1144ff5d5d9a8faef915c23518759b98bebd6efdb6a4b39ea7a11ecd67d63e07847b05982853a20b0a719a855d16a1dcba45f28ac97383478a319ef9281488
6
+ metadata.gz: c79fb3ea3e499fee16fa36f8e10c640a54a1ddc3d0121a99d5053b7c28a60cfbe903f2600c59ec61997a42942f40b16298714904dfbbdb170dbbfa0adf23540b
7
+ data.tar.gz: 4d7a82621d0429c005f4d3743724bc2de51c7f57110416d50a1397de8d6a473e73ec25416f53533b12c500670709412cee6fd73b529fc68dfc044e5112f54578
data/.rubocop.yml CHANGED
@@ -32,6 +32,6 @@ Metrics/BlockLength:
32
32
  - test/**/*
33
33
 
34
34
  Metrics/AbcSize:
35
- Max: 20
35
+ Max: 30
36
36
  IgnoredMethods:
37
- - build_components
37
+ - build_components
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 2.7.1
1
+ ruby 2.7.3
data/Gemfile CHANGED
@@ -5,5 +5,7 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in camalian.gemspec
6
6
  gemspec
7
7
 
8
+ gem 'overcommit', require: false
8
9
  gem 'rubocop', '~> 1.3', require: false
10
+ gem 'rubocop-daemon', require: false
9
11
  gem 'simplecov', require: false
data/README.md CHANGED
@@ -10,7 +10,7 @@ Ruby gem to extract color palettes from images and play with their saturation
10
10
 
11
11
  Add this line to your application's Gemfile:
12
12
 
13
- gem 'camalian', '~> 0.1.1'
13
+ gem 'camalian', '~> 0.2.0'
14
14
 
15
15
  And then execute:
16
16
 
@@ -28,18 +28,26 @@ colors = image.prominent_colors(15)
28
28
  colors = colors.sort_similar_colors
29
29
  colors.light_colors(0, 40)
30
30
  ```
31
-
32
- ### Quantization Algorithms
33
- Currently following algorithms are implemented.
34
31
 
35
- **Histogram**
32
+ You can find a working example with detail explanation and reference code here on [this link](https://basicdrift.com/color-extraction-library-build-color-search-engine-fdf369678d5a). Here we will build a functional color based image search engine in Ruby on Rails.
33
+
34
+ NOTE: Since its a compute intensive operation so for production use its suggested to use under a background job and not within a request/response cycle.
35
+
36
+ ## Quantization Algorithms
37
+
38
+ Currently following algorithms are implemented.
39
+
40
+ ### Histogram
36
41
 
37
- Its a most common algorithm for color quantization and used different bucket technique to group the colors together. You can read more about this technique here https://en.wikipedia.org/wiki/Color_histogram. It can be accessed by `Camalian::QUANTIZATION_HISTOGRAM` constant. This is used as default method as well.
42
+ Its a most common algorithm for color quantization and used different bucket technique to group the colors together. You can read more about this [technique here](https://en.wikipedia.org/wiki/Color_histogram). It can be accessed by `Camalian::QUANTIZATION_HISTOGRAM` constant. This is used as default method as well.
38
43
 
44
+ ### K Means
39
45
 
40
- **K Means**
46
+ This algorithm uses color distancing in RGB space to group the similar colors. You can learn more about this [technique here](https://en.wikipedia.org/wiki/K-means_clustering). It can be accessed by `Camalian::QUANTIZATION_K_MEANS` constant.
41
47
 
42
- This algorithm uses color distancing in RGB space to group the similar colors. You can learn more about this technique here https://en.wikipedia.org/wiki/K-means_clustering. It can be accessed by `Camalian::QUANTIZATION_K_MEANS` constant.
48
+ ### Median Cut
49
+
50
+ This algorithm uses color highest color range to determine the median and split colors to groups. The output consists of average color of such color groups. Since these algorithm don't use actual colors and instead average, so you will may not exact matching pixel in the image. This algorithm is nice to be used with image compression, where similarity and compression is important than having same pixel colors. You can learn more about this [technique here](https://tpgit.github.io/UnOfficialLeptDocs/leptonica/color-quantization.html) . It can be accessed by `Camalian::QUANTIZATION_MEDIAN_CUT` constant.
43
51
 
44
52
 
45
53
  You can set default quantization method globally as:
@@ -55,11 +63,6 @@ image = Camalian::load('file_path')
55
63
  colors = image.prominent_colors(15, quantization: Camalian::QUANTIZATION_K_MEANS)
56
64
  ```
57
65
 
58
- ## Usage
59
- You can find a working example with detail explanation and reference code here on [this link](https://basicdrift.com/color-extraction-library-build-color-search-engine-fdf369678d5a). Here we will build a functional color based image search engine in Ruby on Rails.
60
-
61
- NOTE: Since its a compute intensive operation so for production use its suggested to use under a background job and not within a request/response cycle.
62
-
63
66
  ## Contributing
64
67
 
65
68
  1. Fork it
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ require 'rake/testtask'
6
6
 
7
7
  Rake::TestTask.new do |t|
8
8
  t.libs << 'test'
9
+ t.pattern = 'test/**/*_test.rb'
9
10
  end
10
11
 
11
12
  desc 'Run tests'
data/lib/camalian.rb CHANGED
@@ -10,10 +10,12 @@ require 'camalian/palette'
10
10
  require 'camalian/image'
11
11
  require 'camalian/quantization/histogram'
12
12
  require 'camalian/quantization/k_means'
13
+ require 'camalian/quantization/median_cut'
13
14
 
14
15
  module Camalian # :nodoc:
15
16
  QUANTIZATION_HISTOGRAM = Camalian::Quantization::Histogram
16
17
  QUANTIZATION_K_MEANS = Camalian::Quantization::KMeans
18
+ QUANTIZATION_MEDIAN_CUT = Camalian::Quantization::MedianCut
17
19
 
18
20
  class << self
19
21
  def options
@@ -3,6 +3,10 @@
3
3
  module Camalian
4
4
  # Collection of colors with some useful features
5
5
  class Palette < Array
6
+ def self.from_hex(hex_values)
7
+ new(hex_values.map { |v| Color.from_hex(v) })
8
+ end
9
+
6
10
  def sort_by_lightness
7
11
  Palette.new(sort_by(&:l).reverse)
8
12
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Camalian
4
+ module Quantization
5
+ class MedianCut # :nodoc:
6
+ SplitInfo = Struct.new(:range, :group_index, :color, keyword_init: true)
7
+ def process(colors, count)
8
+ # Its faster to extract unique colors once
9
+ colors = colors.uniq
10
+ groups = [colors]
11
+ limit = [count, colors.size].min
12
+
13
+ loop do
14
+ split_info = determine_group_split(groups)
15
+ group1, group2 = split_group(groups[split_info.group_index], split_info)
16
+ groups.reject!.each_with_index { |_g, index| index == split_info.group_index }
17
+ groups << group1 unless group1.empty?
18
+ groups << group2 unless group2.empty?
19
+
20
+ break if groups.size >= limit
21
+ end
22
+
23
+ palletes = groups.map { |g| Palette.new(g.uniq) }
24
+ average_colors = palletes.map(&:average_color)
25
+
26
+ Palette.new(average_colors[0...count])
27
+ end
28
+
29
+ private
30
+
31
+ def determine_group_split(groups)
32
+ stats = []
33
+
34
+ groups.each_with_index do |group, index|
35
+ reds = group.map(&:r)
36
+ greens = group.map(&:g)
37
+ blues = group.map(&:b)
38
+
39
+ ranges = []
40
+ ranges << SplitInfo.new(group_index: index, range: reds.max - reds.min, color: :r) unless reds.empty?
41
+ ranges << SplitInfo.new(group_index: index, range: greens.max - greens.min, color: :g) unless greens.empty?
42
+ ranges << SplitInfo.new(group_index: index, range: blues.max - blues.min, color: :b) unless blues.empty?
43
+
44
+ stats << ranges.max_by(&:range)
45
+ end
46
+
47
+ stats.max_by(&:range)
48
+ end
49
+
50
+ def split_group(group, split_info)
51
+ split_color = split_info.color
52
+ colors = group.sort_by { |pixel| pixel.send split_color }
53
+
54
+ return [[colors[0]], [colors[1]]] if colors.size == 2
55
+
56
+ median_index = colors.size / 2
57
+ median_value = colors[median_index].send split_color
58
+
59
+ group1 = []
60
+ group2 = []
61
+
62
+ colors.each do |color|
63
+ if color.send(split_color) <= median_value
64
+ group1 << color
65
+ else
66
+ group2 << color
67
+ end
68
+ end
69
+
70
+ [group1, group2]
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Camalian
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
File without changes
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'minitest/autorun'
5
+ require 'minitest/spec'
6
+ require 'camalian'
7
+
8
+ describe Camalian::Palette do
9
+ before do
10
+ mixed_colors = %w[#2560a2 #4dd915 #1530db #49cc23 #45c031 #3da84d #1d48be #399c5b #359069 #318478 #2d7886 #296c94
11
+ #2154b0 #193ccc #41b43f].freeze
12
+
13
+ @palette = Camalian::Palette.from_hex(mixed_colors)
14
+ end
15
+
16
+ it 'initialize palette with correct size' do
17
+ _(@palette.size).must_equal 15
18
+ end
19
+
20
+ describe '#sort_by_lightness' do
21
+ it 'sort colors by lightness ' do
22
+ _(@palette.sort_by_lightness.to_hex).must_equal ['#41b43f', '#45c031', '#1530db', '#49cc23', '#4dd915',
23
+ '#193ccc', '#3da84d', '#1d48be', '#399c5b', '#2154b0',
24
+ '#2560a2', '#359069', '#296c94', '#318478', '#2d7886']
25
+ end
26
+ end
27
+
28
+ describe '#sort_by_hue' do
29
+ it 'sort colors by hue' do
30
+ _(@palette.sort_by_hue.to_hex).must_equal ['#1530db', '#193ccc', '#1d48be', '#2154b0', '#2560a2', '#296c94',
31
+ '#2d7886', '#318478', '#359069', '#399c5b', '#3da84d', '#41b43f',
32
+ '#45c031', '#49cc23', '#4dd915']
33
+ end
34
+ end
35
+
36
+ describe '#sort_by_saturation' do
37
+ it 'sort colors by saturation' do
38
+ _(@palette.sort_by_saturation.to_hex).must_equal ['#1530db', '#4dd915', '#193ccc', '#1d48be', '#49cc23',
39
+ '#2154b0', '#2560a2', '#45c031', '#296c94', '#2d7886',
40
+ '#41b43f', '#3da84d', '#399c5b', '#359069', '#318478']
41
+ end
42
+ end
43
+
44
+ describe '#sort_similar_colors' do
45
+ it 'sort colors by hsv' do
46
+ _(@palette.sort_similar_colors.to_hex).must_equal ['#4dd915', '#49cc23', '#45c031', '#41b43f', '#3da84d',
47
+ '#399c5b', '#359069', '#318478', '#2d7886', '#296c94',
48
+ '#2560a2', '#2154b0', '#1d48be', '#193ccc', '#1530db']
49
+ end
50
+ end
51
+
52
+ describe '#average_color' do
53
+ it 'return one average color' do
54
+ _(@palette.average_color.to_hex).must_equal '#318477'
55
+ end
56
+ end
57
+
58
+ describe '#light_colors' do
59
+ it 'extract light colors in provided limit' do
60
+ _(@palette.light_colors(40, 90).to_hex).must_equal ['#4dd915', '#1530db', '#49cc23', '#45c031', '#3da84d',
61
+ '#1d48be', '#399c5b', '#2154b0', '#193ccc', '#41b43f']
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'minitest/autorun'
5
+ require 'minitest/spec'
6
+ require 'camalian'
7
+
8
+ describe Camalian::Quantization::Histogram do
9
+ describe 'palette with 15 colors extracted' do
10
+ before do
11
+ @image = Camalian.load(File.join(File.dirname(__FILE__), '../assets/palette.png'))
12
+ @palette = @image.prominent_colors(15, optimal: false, quantization: Camalian::QUANTIZATION_HISTOGRAM)
13
+ end
14
+
15
+ it 'must have 15 colors' do
16
+ _(@palette.size).must_equal 15
17
+ end
18
+
19
+ it 'sort similar colors in order' do
20
+ _(@palette.sort_similar_colors.map(&:to_hex)).must_equal PALLET_IMAGE_COLORS
21
+ end
22
+ end
23
+
24
+ it 'should extract distinct colors' do
25
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
26
+ result = Camalian::Quantization::Histogram.new.process(colors, 3)
27
+
28
+ _(result.size).must_equal 3
29
+ _(result).must_equal colors
30
+ end
31
+
32
+ it 'should extract distinct colors lesser than pixels' do
33
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
34
+ result = Camalian::Quantization::Histogram.new.process(colors, 2)
35
+
36
+ _(result.size).must_equal 2
37
+ end
38
+
39
+ it 'should extract distinct colors not more than pixels' do
40
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
41
+ result = Camalian::Quantization::Histogram.new.process(colors, 4)
42
+
43
+ _(result.size).must_equal 3
44
+ end
45
+
46
+ it 'should extract same color' do
47
+ colors = %w[#FF0000 #FF0000 #FF0000].map { |c| Camalian::Color.from_hex(c) }
48
+ result = Camalian::Quantization::Histogram.new.process(colors, 3)
49
+
50
+ _(result.size).must_equal 1
51
+ _(result.to_hex).must_equal ['#ff0000']
52
+ end
53
+
54
+ it 'should extract multiple colors' do
55
+ colors = %w[#FF0000 #FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
56
+ result = Camalian::Quantization::Histogram.new.process(colors, 3)
57
+
58
+ _(result.size).must_equal 3
59
+ _(result.to_hex).must_equal %w[#ff0000 #00ff00 #0000ff]
60
+ end
61
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'minitest/autorun'
5
+ require 'minitest/spec'
6
+ require 'camalian'
7
+
8
+ describe Camalian::Quantization::KMeans do
9
+ describe 'palette with 15 colors extracted' do
10
+ before do
11
+ @image = Camalian.load(File.join(File.dirname(__FILE__), '../assets/palette.png'))
12
+ @palette = @image.prominent_colors(15, optimal: false, quantization: Camalian::QUANTIZATION_K_MEANS)
13
+ end
14
+
15
+ it 'must have 15 colors' do
16
+ _(@palette.size).must_equal 15
17
+ end
18
+
19
+ it 'sort similar colors in order' do
20
+ _(@palette.sort_similar_colors.map(&:to_hex)).must_equal PALLET_IMAGE_COLORS
21
+ end
22
+ end
23
+
24
+ it 'should extract distinct colors' do
25
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
26
+ result = Camalian::Quantization::KMeans.new.process(colors, 3)
27
+
28
+ _(result.size).must_equal 3
29
+ _(result).must_equal colors
30
+ end
31
+
32
+ it 'should extract distinct colors lesser than pixels' do
33
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
34
+ result = Camalian::Quantization::KMeans.new.process(colors, 2)
35
+
36
+ _(result.size).must_equal 2
37
+ end
38
+
39
+ it 'should extract distinct colors not more than pixels' do
40
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
41
+ result = Camalian::Quantization::KMeans.new.process(colors, 4)
42
+
43
+ _(result.size).must_equal 3
44
+ end
45
+
46
+ it 'should extract same color' do
47
+ colors = %w[#FF0000 #FF0000 #FF0000].map { |c| Camalian::Color.from_hex(c) }
48
+ result = Camalian::Quantization::KMeans.new.process(colors, 3)
49
+
50
+ _(result.size).must_equal 1
51
+ _(result.to_hex).must_equal ['#ff0000']
52
+ end
53
+
54
+ it 'should extract multiple colors' do
55
+ colors = %w[#FF0000 #FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
56
+ result = Camalian::Quantization::KMeans.new.process(colors, 3)
57
+
58
+ _(result.size).must_equal 3
59
+ _(result.to_hex).must_equal %w[#ff0000 #00ff00 #0000ff]
60
+ end
61
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'minitest/autorun'
5
+ require 'minitest/spec'
6
+ require 'camalian'
7
+
8
+ describe Camalian::Quantization::MedianCut do
9
+ describe 'palette with 15 colors extracted' do
10
+ before do
11
+ @image = Camalian.load(File.join(File.dirname(__FILE__), '../assets/palette.png'))
12
+ @palette = @image.prominent_colors(15, optimal: false, quantization: Camalian::QUANTIZATION_MEDIAN_CUT)
13
+ end
14
+
15
+ it 'must have 15 colors' do
16
+ _(@palette.size).must_equal 15
17
+ end
18
+
19
+ it 'sort similar colors in order' do
20
+ _(@palette.sort_similar_colors.map(&:to_hex)).must_equal ['#4dd915', '#49cc23', '#45c031', '#41b43f', '#3da84d',
21
+ '#399c5b', '#359069', '#318478', '#2d7886', '#296c94',
22
+ '#2560a2', '#2154b0', '#1d48be', '#193ccc', '#1530db']
23
+ end
24
+ end
25
+
26
+ it 'should extract distinct colors' do
27
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
28
+ result = Camalian::Quantization::MedianCut.new.process(colors, 3)
29
+
30
+ _(result.size).must_equal 3
31
+ _(result.to_hex.sort).must_equal colors.map(&:to_hex).sort
32
+ end
33
+
34
+ it 'should extract distinct colors lesser than pixels' do
35
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
36
+ result = Camalian::Quantization::MedianCut.new.process(colors, 2)
37
+
38
+ _(result.size).must_equal 2
39
+ end
40
+
41
+ it 'should extract distinct colors not more than pixels' do
42
+ colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
43
+ result = Camalian::Quantization::MedianCut.new.process(colors, 4)
44
+
45
+ _(result.size).must_equal 3
46
+ end
47
+
48
+ it 'should extract same color' do
49
+ colors = %w[#FF0000 #FF0000 #FF0000].map { |c| Camalian::Color.from_hex(c) }
50
+ result = Camalian::Quantization::MedianCut.new.process(colors, 3)
51
+
52
+ _(result.size).must_equal 1
53
+ _(result.to_hex).must_equal ['#ff0000']
54
+ end
55
+
56
+ it 'only: should extract multiple colors' do
57
+ colors = %w[#FF0000 #FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
58
+ result = Camalian::Quantization::MedianCut.new.process(colors, 3)
59
+
60
+ _(result.size).must_equal 3
61
+ _(result.to_hex).must_equal ['#ff0000', '#0000ff', '#00ff00']
62
+ end
63
+ end
data/test/test_helper.rb CHANGED
@@ -6,3 +6,6 @@ SimpleCov.start
6
6
  require 'minitest/autorun'
7
7
  require 'minitest/spec'
8
8
  require 'camalian'
9
+
10
+ PALLET_IMAGE_COLORS = %w[#4dd915 #49cc23 #45c031 #41b43f #3da84d #399c5b #359069 #318478 #2d7886 #296c94 #2560a2
11
+ #2154b0 #1d48be #193ccc #1530db].freeze
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: camalian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nazar Hussain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-29 00:00:00.000000000 Z
11
+ date: 2021-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chunky_png
@@ -96,12 +96,15 @@ files:
96
96
  - lib/camalian/palette.rb
97
97
  - lib/camalian/quantization/histogram.rb
98
98
  - lib/camalian/quantization/k_means.rb
99
+ - lib/camalian/quantization/median_cut.rb
99
100
  - lib/camalian/version.rb
100
101
  - test/assets/palette.png
101
- - test/test_color.rb
102
+ - test/color_test.rb
103
+ - test/palette_test.rb
104
+ - test/quantization/histogram_test.rb
105
+ - test/quantization/k_means_test.rb
106
+ - test/quantization/median_cut_test.rb
102
107
  - test/test_helper.rb
103
- - test/test_palette.rb
104
- - test/test_quantization.rb
105
108
  homepage: https://github.com/nazarhussain/camalian
106
109
  licenses:
107
110
  - MIT
@@ -121,14 +124,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
124
  - !ruby/object:Gem::Version
122
125
  version: '0'
123
126
  requirements: []
124
- rubygems_version: 3.0.3
127
+ rubygems_version: 3.0.3.1
125
128
  signing_key:
126
129
  specification_version: 4
127
130
  summary: Library used to deal with colors and images. You can extract colors from
128
131
  images.
129
132
  test_files:
130
133
  - test/assets/palette.png
131
- - test/test_color.rb
134
+ - test/color_test.rb
135
+ - test/palette_test.rb
136
+ - test/quantization/histogram_test.rb
137
+ - test/quantization/k_means_test.rb
138
+ - test/quantization/median_cut_test.rb
132
139
  - test/test_helper.rb
133
- - test/test_palette.rb
134
- - test/test_quantization.rb
data/test/test_palette.rb DELETED
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
- require 'minitest/autorun'
5
- require 'minitest/spec'
6
- require 'camalian'
7
-
8
- PALLET_IMAGE_COLORS = %w[#4dd915 #49cc23 #45c031 #41b43f #3da84d #399c5b #359069 #318478 #2d7886 #296c94 #2560a2
9
- #2154b0 #1d48be #193ccc #1530db].freeze
10
-
11
- describe Camalian::Palette do
12
- before do
13
- @image = Camalian.load(File.join(File.dirname(__FILE__), 'assets/palette.png'))
14
- @palette = @image.prominent_colors(15, optimal: false)
15
- end
16
-
17
- describe 'palette with 15 colors extracted' do
18
- it 'must have 15 colors' do
19
- _(@palette.size).must_equal 15
20
- end
21
-
22
- it 'sort similar colors in order' do
23
- _(@palette.sort_similar_colors.map(&:to_hex)).must_equal PALLET_IMAGE_COLORS
24
- end
25
-
26
- it 'color with intensity 0-40 works well' do
27
- _(@palette.light_colors(0, 40).map(&:to_hex)).must_equal %w[#2560a2 #296c94 #2d7886 #318478 #359069]
28
- end
29
- end
30
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- describe Camalian::Quantization do
6
- [Camalian::Quantization::KMeans, Camalian::Quantization::Histogram].each do |klass|
7
- describe klass.name.to_s do
8
- it 'should extract distinct colors' do
9
- colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
10
- result = klass.new.process(colors, 3)
11
-
12
- _(result.size).must_equal 3
13
- _(result).must_equal colors
14
- end
15
-
16
- it 'should extract distinct colors lesser than pixels' do
17
- colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
18
- result = klass.new.process(colors, 2)
19
-
20
- _(result.size).must_equal 2
21
- end
22
-
23
- it 'should extract distinct colors not more than pixels' do
24
- colors = %w[#FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
25
- result = klass.new.process(colors, 4)
26
-
27
- _(result.size).must_equal 3
28
- end
29
-
30
- it 'should extract same color' do
31
- colors = %w[#FF0000 #FF0000 #FF0000].map { |c| Camalian::Color.from_hex(c) }
32
- result = klass.new.process(colors, 3)
33
-
34
- _(result.size).must_equal 1
35
- _(result.to_hex).must_equal ['#ff0000']
36
- end
37
-
38
- it 'should extract multiple colors' do
39
- colors = %w[#FF0000 #FF0000 #00FF00 #0000FF].map { |c| Camalian::Color.from_hex(c) }
40
- result = klass.new.process(colors, 3)
41
-
42
- _(result.size).must_equal 3
43
- _(result.to_hex).must_equal %w[#ff0000 #00ff00 #0000ff]
44
- end
45
- end
46
- end
47
- end