camalian 0.0.3 → 0.1.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
- SHA1:
3
- metadata.gz: cbf6f55fe49509d8e0ae73b3ee3717026bea081f
4
- data.tar.gz: 810535ed27dcd19b903aedbe3b2825baf7ce4ea3
2
+ SHA256:
3
+ metadata.gz: bdc6f4d61421eac9f0017baf9e6f290c37e47b633ee4533e18d00883fd162b54
4
+ data.tar.gz: 5cb477be826b4c0706a9385ce31699a34aab8b27c66c5c57140d1818650ca60e
5
5
  SHA512:
6
- metadata.gz: cbbf8aca2ebe72c607b6dc1a38fb2ca5adb36a15590088e30643c25ba67e7fd8c3a0eee0b1907c03a9e13342c258f5642ab3fe7b2e94c08ea8eb841e92d944e8
7
- data.tar.gz: 8c13c34b6c99cd644eed763d1e36d90304a3116b96adcb1edd26e85da5884aec596e6ffc9ab67dafc382113900286dd0714ec7b8cec94558e3bc08fa66f3f687
6
+ metadata.gz: 912bcad8d3db3362d2997877fe42b9d2df01c806b9bbfe965463d5df8e530dab55f716820f414e44910e5818ff86ac1ac256f8c9d1a2d760ca75d38c69492dcc
7
+ data.tar.gz: fe6989ee96c21f12482857c26aed89f7db69e6d1a41616c9aaed3a11732ccf76c8376c6711b49dc375cbb8d29adfef1ff09ba3ea3c5780c4f70cdce0431041eb
@@ -0,0 +1,30 @@
1
+ name: Github Packages Push
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ tags:
7
+ - '*'
8
+ jobs:
9
+ build:
10
+ name: Build + Publish
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Set up Ruby 2.6
16
+ uses: actions/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.6.x
19
+
20
+ - name: Publish to GPR
21
+ run: |
22
+ mkdir -p $HOME/.gem
23
+ touch $HOME/.gem/credentials
24
+ chmod 0600 $HOME/.gem/credentials
25
+ printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
26
+ gem build *.gemspec
27
+ gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
28
+ env:
29
+ GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
30
+ OWNER: ${{ github.repository_owner }}
@@ -0,0 +1,32 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: build
9
+
10
+ on:
11
+ push:
12
+ branches: [ master ]
13
+ pull_request:
14
+ branches: [ master ]
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ubuntu-16.04
19
+ strategy:
20
+ matrix:
21
+ ruby: [ '2.4', '2.5', '2.6', '2.7' ]
22
+ name: Ruby ${{ matrix.ruby }}
23
+ steps:
24
+ - uses: actions/checkout@v2
25
+ - uses: actions/setup-ruby@v1
26
+ with:
27
+ ruby-version: ${{ matrix.ruby }}
28
+ - name: Install dependencies
29
+ run: bundle install
30
+ - name: Run tests
31
+ run: bundle exec rake
32
+
@@ -0,0 +1,29 @@
1
+ name: Ruby Gems Push
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ tags:
7
+ - '*'
8
+ jobs:
9
+ build:
10
+ name: Build + Publish
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Set up Ruby 2.6
16
+ uses: actions/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.6.x
19
+
20
+ - name: Publish to RubyGems
21
+ run: |
22
+ mkdir -p $HOME/.gem
23
+ touch $HOME/.gem/credentials
24
+ chmod 0600 $HOME/.gem/credentials
25
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
26
+ gem build *.gemspec
27
+ gem push *.gem
28
+ env:
29
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
data/.gitignore CHANGED
@@ -15,4 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
- .idea/
18
+ .idea/
19
+ coverage/
@@ -0,0 +1,33 @@
1
+ # Use this file to configure the Overcommit hooks you wish to use. This will
2
+ # extend the default configuration defined in:
3
+ # https://github.com/sds/overcommit/blob/master/config/default.yml
4
+ #
5
+ # At the topmost level of this YAML file is a key representing type of hook
6
+ # being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
7
+ # customize each hook, such as whether to only run it on certain files (via
8
+ # `include`), whether to only display output if it fails (via `quiet`), etc.
9
+ #
10
+ # For a complete list of hooks, see:
11
+ # https://github.com/sds/overcommit/tree/master/lib/overcommit/hook
12
+ #
13
+ # For a complete list of options that you can use to customize hooks, see:
14
+ # https://github.com/sds/overcommit#configuration
15
+ #
16
+ # Uncomment the following lines to make the configuration take effect.
17
+
18
+ PreCommit:
19
+ RuboCop:
20
+ enabled: true
21
+ on_warn: fail # Treat all warnings as failures
22
+
23
+ # TrailingWhitespace:
24
+ # enabled: true
25
+ # exclude:
26
+ # - '**/db/structure.sql' # Ignore trailing whitespace in generated files
27
+ #
28
+ #PostCheckout:
29
+ # ALL: # Special hook name that customizes all hooks of this type
30
+ # quiet: true # Change all post-checkout hooks to only display output on failure
31
+ #
32
+ # IndexTags:
33
+ # enabled: true # Generate a tags file with `ctags` each time HEAD changes
@@ -0,0 +1,33 @@
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://docs.rubocop.org/rubocop/configuration
11
+
12
+ AllCops:
13
+ NewCops: enable
14
+
15
+ Naming/MethodParameterName:
16
+ AllowedNames:
17
+ - r
18
+ - g
19
+ - b
20
+
21
+ Metrics/MethodLength:
22
+ Max: 50
23
+
24
+ Metrics/PerceivedComplexity:
25
+ Max: 25
26
+
27
+ Metrics/CyclomaticComplexity:
28
+ Max: 15
29
+
30
+ Metrics/AbcSize:
31
+ Max: 20
32
+ IgnoredMethods:
33
+ - build_components
@@ -0,0 +1 @@
1
+ ruby 2.7.1
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.7
4
+ - 2.6
5
+ - 2.5
6
+ - 2.4
7
+
8
+ before_script:
9
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
10
+ - chmod +x ./cc-test-reporter
11
+ - ./cc-test-reporter before-build
12
+
13
+ script:
14
+ - bundle exec rake test
15
+
16
+ after_script:
17
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/Gemfile CHANGED
@@ -1,4 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in camalian.gemspec
4
6
  gemspec
7
+
8
+ gem 'rubocop', '~> 1.3', require: false
9
+ gem 'simplecov', require: false
data/README.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # Camalian
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/camalian.svg)](https://badge.fury.io/rb/camalian)
4
+ ![Ruby](https://github.com/nazarhussain/camalian/workflows/build/badge.svg?branch=master)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/5495a2c122469d81b6c5/maintainability)](https://codeclimate.com/github/nazarhussain/camalian/maintainability)
6
+
3
7
  Ruby gem to extract color palettes from images and play with their saturation
4
8
 
5
9
  ## Installation
6
10
 
7
11
  Add this line to your application's Gemfile:
8
12
 
9
- gem 'camalian', '~> 0.0.3'
13
+ gem 'camalian', '~> 0.1.0'
10
14
 
11
15
  And then execute:
12
16
 
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
2
4
 
3
5
  require 'rake/testtask'
4
6
 
@@ -6,5 +8,5 @@ Rake::TestTask.new do |t|
6
8
  t.libs << 'test'
7
9
  end
8
10
 
9
- desc "Run tests"
10
- task :default => :test
11
+ desc 'Run tests'
12
+ task default: :test
@@ -1,27 +1,28 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'camalian/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "camalian"
8
+ spec.name = 'camalian'
8
9
  spec.version = Camalian::VERSION
9
- spec.authors = ["Nazar Hussain"]
10
- spec.email = ["nazarhussain@gmail.com"]
11
- spec.description = %q{Library used to deal with colors and images}
12
- spec.summary = %q{Library used to deal with colors and images. You can extract colors from images.}
13
- spec.homepage = "https://github.com/nazarhussain/camalian"
14
- spec.license = "MIT"
10
+ spec.authors = ['Nazar Hussain']
11
+ spec.email = ['nazarhussain@gmail.com']
12
+ spec.description = 'Library used to deal with colors and images'
13
+ spec.summary = 'Library used to deal with colors and images. You can extract colors from images.'
14
+ spec.homepage = 'https://github.com/nazarhussain/camalian'
15
+ spec.license = 'MIT'
15
16
 
16
- spec.files = `git ls-files`.split($/)
17
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
20
21
 
21
- spec.requirements = 'ImageMagick'
22
+ spec.add_dependency 'chunky_png', '~> 1.3', '>= 1.3.14'
22
23
 
23
- spec.add_dependency "cocaine"
24
- spec.add_dependency "rmagick", "~> 2.15.4"
25
- spec.add_dependency "oily_png", "~> 1.2.0"
24
+ spec.add_development_dependency 'minitest', '~> 5.14', '>= 5.14.2'
25
+ spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
26
26
 
27
+ spec.required_ruby_version = '>= 2.4'
27
28
  end
@@ -1,25 +1,27 @@
1
- require "oily_png"
2
- require "tempfile"
3
- require "open-uri"
4
- require "cocaine"
5
- require "chunky_png_patch/color"
1
+ # frozen_string_literal: true
6
2
 
7
- require "camalian/version"
8
- require "camalian/color"
9
- require "camalian/palette"
10
- require "camalian/image"
3
+ require 'chunky_png'
4
+ require 'tempfile'
5
+ require 'open-uri'
6
+
7
+ require 'camalian/version'
8
+ require 'camalian/color'
9
+ require 'camalian/palette'
10
+ require 'camalian/image'
11
+ require 'camalian/quantization/histogram'
12
+
13
+ module Camalian # :nodoc:
14
+ QUANTIZATION_HISTOGRAM = 'histogram'
11
15
 
12
- module Camalian
13
16
  class << self
14
17
  def options
15
- convert = `which convert`.strip
16
18
  @options ||= {
17
- :image_magick_path => convert.length > 0 ? convert : '/usr/bin/convert',
18
- :color_count => 8,
19
+ color_count: 8,
20
+ quantization: Camalian::QUANTIZATION_HISTOGRAM
19
21
  }
20
22
  end
21
23
 
22
- def load(image_path)
24
+ def load(image_path)
23
25
  Image.new(image_path)
24
26
  end
25
27
  end
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Camalian
4
+ # Camalian color object
2
5
  class Color
3
-
4
6
  attr_reader :r, :g, :b, :h, :s, :l, :hsv
5
7
 
6
- def initialize(*value)
7
- if value.size == 1
8
- rgb = extract_rgb(value.first)
9
- build_components(rgb[0], rgb[1], rgb[2])
10
- elsif value.size == 3
11
- build_components(value[0], value[1], value[2])
12
- end
8
+ def initialize(r, g, b)
9
+ build_components(r, g, b)
10
+ end
11
+
12
+ def self.from_hex(hex_value)
13
+ r, g, b = extract_rgb(hex_value)
14
+ Color.new(r, g, b)
13
15
  end
14
16
 
15
17
  def to_s
@@ -21,7 +23,7 @@ module Camalian
21
23
  end
22
24
 
23
25
  def distance(color)
24
- [(self.h - color.h) % 360, (color.h - self.h) % 360].min
26
+ [(h - color.h) % 360, (color.h - h) % 360].min
25
27
  end
26
28
 
27
29
  def extract_rgb(color_hash)
@@ -35,7 +37,7 @@ module Camalian
35
37
 
36
38
  private
37
39
 
38
- def build_components(r,g,b)
40
+ def build_components(r, g, b)
39
41
  @r = r
40
42
  @g = g
41
43
  @b = b
@@ -50,21 +52,21 @@ module Camalian
50
52
 
51
53
  @l = (cmax + cmin) / 2.0
52
54
 
53
- if delta == 0
55
+ if delta.zero?
54
56
  @h = 0
55
57
  elsif cmax == ri
56
58
  @h = 60 * (((gi - bi) / delta) % 6)
57
59
  elsif cmax == gi
58
- @h = 60 * (((bi - ri)/ delta) + 2)
60
+ @h = 60 * (((bi - ri) / delta) + 2)
59
61
  elsif cmax == bi
60
- @h = 60 * (((ri - gi)/ delta) + 4)
62
+ @h = 60 * (((ri - gi) / delta) + 4)
61
63
  end
62
64
 
63
- if (delta == 0)
64
- @s = 0
65
- else
66
- @s = delta / ( 1 - (2*@l -1).abs )
67
- end
65
+ @s = if delta.zero?
66
+ 0
67
+ else
68
+ delta / (1 - (2 * @l - 1).abs)
69
+ end
68
70
 
69
71
  @h = @h.round(2)
70
72
  @s = (@s * 100).round(2)
@@ -72,22 +74,22 @@ module Camalian
72
74
 
73
75
  # HSV Calculation
74
76
  # Hue calculation
75
- if delta == 0
77
+ if delta.zero?
76
78
  @hsv = [0]
77
79
  elsif cmax == ri
78
80
  @hsv = [60 * (((gi - bi) / delta) % 6)]
79
81
  elsif cmax == gi
80
- @hsv = [60 * (((bi - ri)/ delta) + 2)]
82
+ @hsv = [60 * (((bi - ri) / delta) + 2)]
81
83
  elsif cmax == bi
82
- @hsv = [60 * (((ri - gi)/ delta) + 4)]
84
+ @hsv = [60 * (((ri - gi) / delta) + 4)]
83
85
  end
84
86
 
85
87
  # Saturation calculation
86
- if (cmax == 0)
87
- @hsv << 0
88
- else
89
- @hsv << delta / cmax
90
- end
88
+ @hsv << if cmax.zero?
89
+ 0
90
+ else
91
+ delta / cmax
92
+ end
91
93
 
92
94
  # Value calculation
93
95
  @hsv << cmax
@@ -1,6 +1,7 @@
1
- require 'rmagick'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Camalian
4
+ # Load image into Camalian
4
5
  class Image
5
6
  attr_accessor :src_file_path
6
7
 
@@ -8,29 +9,30 @@ module Camalian
8
9
  @src_file_path = file_path
9
10
  end
10
11
 
11
- def prominent_colors(count=Camalian.options[:color_count])
12
- image = ::Magick::Image.read(@src_file_path)[0]
13
- image.resize!(100,100)
14
- colors = Palette.new
15
- initial_count = count
16
- q = nil
17
- loop do
18
- q = image.quantize(initial_count, Magick::RGBColorspace)
19
- break if q.color_histogram.size > count
20
- initial_count = initial_count + 10
12
+ def prominent_colors(count = Camalian.options[:color_count],
13
+ quantization: Camalian.options[:quantization],
14
+ optimal: true)
15
+ image = ::ChunkyPNG::Image.from_file(@src_file_path)
16
+
17
+ colors = image.pixels.map do |val|
18
+ Color.new(
19
+ ChunkyPNG::Color.r(val),
20
+ ChunkyPNG::Color.g(val),
21
+ ChunkyPNG::Color.b(val)
22
+ )
21
23
  end
22
- palette = q.color_histogram.sort {|a, b| b[1] <=> a[1]}
23
- (0..[count, palette.count].min - 1).each do |i|
24
- c = palette[i].first.to_s.split(',').map {|x| x[/\d+/]}
25
- c.pop
26
- c[0], c[1], c[2] = [c[0], c[1], c[2]].map { |s|
27
- s = s.to_i
28
- s = s / 256 if s / 256 > 0 # not all ImageMagicks are created equal....
29
- s
30
- }
31
- colors << Color.new(c[0],c[1],c[2])
24
+
25
+ quantize = Object.const_get("Camalian::Quantization::#{quantization.capitalize}").new
26
+
27
+ palette = quantize.process(colors, count)
28
+
29
+ retry_count = 1
30
+ while !optimal && palette.size < count
31
+ palette = quantize.process(colors, count + retry_count)
32
+ retry_count += 1
32
33
  end
33
- return colors.uniq(&:to_hex)
34
+
35
+ palette
34
36
  end
35
37
  end
36
38
  end
@@ -1,26 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Camalian
4
+ # Collection of colors with some useful features
2
5
  class Palette < Array
3
-
4
6
  def sort_by_lightness
5
- Palette.new(self.sort_by { |a| a.l }.reverse)
7
+ Palette.new(sort_by(&:l).reverse)
6
8
  end
7
9
 
8
10
  def sort_by_hue
9
- Palette.new(self.sort_by { |a| a.h }.reverse)
11
+ Palette.new(sort_by(&:h).reverse)
10
12
  end
11
13
 
12
14
  def sort_similar_colors
13
- Palette.new(self.sort_by { |a| a.hsv })
15
+ Palette.new(sort_by(&:hsv))
14
16
  end
15
17
 
16
18
  def sort_by_saturation
17
- Palette.new(self.sort_by { |a| a.s }.reverse)
19
+ Palette.new(sort_by(&:s).reverse)
20
+ end
21
+
22
+ def average_color
23
+ r = map(&:r).inject(&:+)
24
+ g = map(&:g).inject(&:+)
25
+ b = map(&:b).inject(&:+)
26
+ size = self.size
27
+
28
+ Color.new(r / size, g / size, b / size)
18
29
  end
19
30
 
20
31
  def light_colors(limit1, limit2)
21
32
  min = [limit1, limit2].min
22
33
  max = [limit1, limit2].max
23
- table = self.dup
34
+ table = dup
24
35
  Palette.new(table.delete_if { |color| color.l > max or color.l < min })
25
36
  end
26
37
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Camalian
4
+ module Quantization
5
+ class Histogram # :nodoc:
6
+ def process(colors, count)
7
+ bucket_size = (255.0 / count).ceil
8
+ buckets = {}
9
+
10
+ colors.each do |color|
11
+ key = bucket_key(color, bucket_size)
12
+ buckets[key] ||= Palette.new
13
+ buckets[key].push(color)
14
+ end
15
+
16
+ Palette.new(buckets.map { |_, value| value.average_color })
17
+ end
18
+
19
+ private
20
+
21
+ def bucket_key(color, bucket_size)
22
+ "#{color.r / bucket_size}:#{color.g / bucket_size}:#{color.b / bucket_size}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Camalian
2
- VERSION = "0.0.3"
4
+ VERSION = '0.1.0'
3
5
  end
Binary file
@@ -1,29 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
1
4
  require 'minitest/autorun'
2
5
  require 'minitest/spec'
3
6
  require 'camalian'
4
7
 
5
8
  describe Camalian::Color do
6
9
  before do
7
- @color = Camalian::Color.new(120,255,30)
10
+ @color = Camalian::Color.new(120, 255, 30)
8
11
  end
9
12
 
10
- describe "Color initialized with 120, 255, 30 rgb values" do
11
- it "hex value must be #78ff1e" do
12
- @color.to_hex.must_equal "#78ff1e"
13
+ describe 'Color initialized with 120, 255, 30 rgb values' do
14
+ it 'hex value must be #78ff1e' do
15
+ _(@color.to_hex).must_equal '#78ff1e'
13
16
  end
14
17
 
15
- it "hsl color components must " do
16
- [@color.h.to_i, @color.s.to_i, @color.l.to_i].must_equal [96, 100, 55]
18
+ it 'hsl color components must ' do
19
+ _([@color.h.to_i, @color.s.to_i, @color.l.to_i]).must_equal [96, 100, 55]
17
20
  end
18
21
 
19
- it "hsv color components must " do
20
- @color.hsv.map(&:to_i).must_equal [96, 88, 100]
22
+ it 'hsv color components must ' do
23
+ _(@color.hsv.map(&:to_i)).must_equal [96, 88, 100]
21
24
  end
22
25
  end
23
26
 
24
- describe "initialized with 1 integer rgb value" do
25
- it "must have leading zero" do
26
- Camalian::Color.new(7, 7, 7).to_hex.must_equal "#070707"
27
+ describe 'initialized with 1 integer rgb value' do
28
+ it 'must have leading zero' do
29
+ _(Camalian::Color.new(7, 7, 7).to_hex).must_equal '#070707'
27
30
  end
28
31
  end
29
32
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start
@@ -1,28 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
1
4
  require 'minitest/autorun'
2
5
  require 'minitest/spec'
3
6
  require 'camalian'
4
7
 
5
- describe Camalian::Image do
6
-
7
- end
8
+ PALLET_IMAGE_COLORS = %w[#4dd915 #49cc23 #45c031 #41b43f #3da84d #399c5b #359069 #318478 #2d7886 #296c94 #2560a2
9
+ #2154b0 #1d48be #193ccc #1530db].freeze
8
10
 
9
11
  describe Camalian::Palette do
10
12
  before do
11
- @image = Camalian::load( File.join( File.dirname(__FILE__), 'assets/palette.png'))
12
- @palette = @image.prominent_colors(15)
13
+ @image = Camalian.load(File.join(File.dirname(__FILE__), 'assets/palette.png'))
14
+ @palette = @image.prominent_colors(15, optimal: false)
13
15
  end
14
16
 
15
- describe "palette with 15 colors extracted" do
16
- it "must have 15 colors" do
17
- @palette.size.must_equal 15
17
+ describe 'palette with 15 colors extracted' do
18
+ it 'must have 15 colors' do
19
+ _(@palette.size).must_equal 15
18
20
  end
19
21
 
20
- it "sort similar colors in order" do
21
- @palette.sort_similar_colors.map(&:to_hex).must_equal %W(#4dda15 #45c131 #41b53f #3da94d #3da84e #359169 #318578 #2d7986 #296d94 #2560a3 #2154b1 #1d48bf #193dcd #193cce #1530dc)
22
+ it 'sort similar colors in order' do
23
+ _(@palette.sort_similar_colors.map(&:to_hex)).must_equal PALLET_IMAGE_COLORS
22
24
  end
23
25
 
24
- it "color with intensity 0-40 works well" do
25
- @palette.light_colors(0, 40).map(&:to_hex).must_equal %W(#318578 #2560a3 #359169 #296d94 #2d7986)
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]
26
28
  end
27
29
  end
28
30
  end
metadata CHANGED
@@ -1,57 +1,75 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: camalian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.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: 2015-11-30 00:00:00.000000000 Z
11
+ date: 2020-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: cocaine
14
+ name: chunky_png
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
17
20
  - - ">="
18
21
  - !ruby/object:Gem::Version
19
- version: '0'
22
+ version: 1.3.14
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
24
30
  - - ">="
25
31
  - !ruby/object:Gem::Version
26
- version: '0'
32
+ version: 1.3.14
27
33
  - !ruby/object:Gem::Dependency
28
- name: rmagick
34
+ name: minitest
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: 2.15.4
34
- type: :runtime
39
+ version: '5.14'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 5.14.2
43
+ type: :development
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
47
  - - "~>"
39
48
  - !ruby/object:Gem::Version
40
- version: 2.15.4
49
+ version: '5.14'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 5.14.2
41
53
  - !ruby/object:Gem::Dependency
42
- name: oily_png
54
+ name: rake
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
57
  - - "~>"
46
58
  - !ruby/object:Gem::Version
47
- version: 1.2.0
48
- type: :runtime
59
+ version: '13.0'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 13.0.1
63
+ type: :development
49
64
  prerelease: false
50
65
  version_requirements: !ruby/object:Gem::Requirement
51
66
  requirements:
52
67
  - - "~>"
53
68
  - !ruby/object:Gem::Version
54
- version: 1.2.0
69
+ version: '13.0'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 13.0.1
55
73
  description: Library used to deal with colors and images
56
74
  email:
57
75
  - nazarhussain@gmail.com
@@ -59,7 +77,14 @@ executables: []
59
77
  extensions: []
60
78
  extra_rdoc_files: []
61
79
  files:
80
+ - ".github/workflows/gpr-push.yml"
81
+ - ".github/workflows/ruby.yml"
82
+ - ".github/workflows/rubygems-push.yml"
62
83
  - ".gitignore"
84
+ - ".overcommit.yml"
85
+ - ".rubocop.yml"
86
+ - ".tool-versions"
87
+ - ".travis.yml"
63
88
  - Gemfile
64
89
  - LICENSE.txt
65
90
  - README.md
@@ -69,10 +94,11 @@ files:
69
94
  - lib/camalian/color.rb
70
95
  - lib/camalian/image.rb
71
96
  - lib/camalian/palette.rb
97
+ - lib/camalian/quantization/histogram.rb
72
98
  - lib/camalian/version.rb
73
- - lib/chunky_png_patch/color.rb
74
99
  - test/assets/palette.png
75
100
  - test/test_color.rb
101
+ - test/test_helper.rb
76
102
  - test/test_palette.rb
77
103
  homepage: https://github.com/nazarhussain/camalian
78
104
  licenses:
@@ -86,16 +112,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
112
  requirements:
87
113
  - - ">="
88
114
  - !ruby/object:Gem::Version
89
- version: '0'
115
+ version: '2.4'
90
116
  required_rubygems_version: !ruby/object:Gem::Requirement
91
117
  requirements:
92
118
  - - ">="
93
119
  - !ruby/object:Gem::Version
94
120
  version: '0'
95
- requirements:
96
- - ImageMagick
97
- rubyforge_project:
98
- rubygems_version: 2.4.5
121
+ requirements: []
122
+ rubygems_version: 3.0.3
99
123
  signing_key:
100
124
  specification_version: 4
101
125
  summary: Library used to deal with colors and images. You can extract colors from
@@ -103,4 +127,5 @@ summary: Library used to deal with colors and images. You can extract colors fro
103
127
  test_files:
104
128
  - test/assets/palette.png
105
129
  - test/test_color.rb
130
+ - test/test_helper.rb
106
131
  - test/test_palette.rb
@@ -1,14 +0,0 @@
1
- module ChunkyPNG::Color
2
- # See http://en.wikipedia.org/wiki/Hue#Computing_hue_from_RGB
3
- def self.hue(pixel)
4
- r, g, b = r(pixel), g(pixel), b(pixel)
5
- return 0 if r == b and b == g
6
- ((180 / Math::PI * Math.atan2((2 * r) - g - b, Math.sqrt(3) * (g - b))) - 90) % 360
7
- end
8
-
9
- # The modular distance, as the hue is circular
10
- def self.distance(pixel, poxel)
11
- hue_pixel, hue_poxel = hue(pixel), hue(poxel)
12
- [(hue_pixel - hue_poxel) % 360, (hue_poxel - hue_pixel) % 360].min
13
- end
14
- end