camalian 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6d00dedccb6e595bdc20ada99a24660c6ae5dd3d
4
+ data.tar.gz: 5c0dbce2351031926ae80fd502d96f14899c83c6
5
+ SHA512:
6
+ metadata.gz: e7cf381751a54732d7a08474333accca30b0b5284c0916373f88c739e1951f4557469c5c5611d719200e29d5c1c5403aa87d7143395fbf3e96b311d55d66a9d2
7
+ data.tar.gz: bf78a507dcec731e88d8fe13c0f6e5e962529bf644d5fb49b9d760518ebf1352c25108a4f1e3ee4fab726c663b773bdcb0ff3aa6a975b359c4f9771a4dbad57c
data/.gitignore CHANGED
File without changes
data/Gemfile CHANGED
File without changes
File without changes
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Camalian
2
2
 
3
- TODO: Write a gem description
3
+ Ruby gem to extract color palettes from images and play with their saturation
4
4
 
5
5
  ## Installation
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
- gem 'camalian'
9
+ gem 'camalian', '~> 0.0.2'
10
10
 
11
11
  And then execute:
12
12
 
@@ -18,7 +18,10 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- TODO: Write usage instructions here
21
+ image = Camalian::load('file_path')
22
+ colors = image.prominent_colors(15)
23
+ colors = colors.sort_similar_colors
24
+ colors.light_colors(0, 40)
22
25
 
23
26
  ## Contributing
24
27
 
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["nazarhussain@gmail.com"]
11
11
  spec.description = %q{Library used to deal with colors and images}
12
12
  spec.summary = %q{Library used to deal with colors and images. You can extract colors from images.}
13
- spec.homepage = "http://www.nazarhussain.com"
13
+ spec.homepage = "https://github.com/nazarhussain/camalian"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -18,4 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.requirements = 'ImageMagick'
22
+
23
+ spec.add_dependency "cocaine"
24
+ spec.add_dependency "rmagick", "~> 2.15.4"
25
+ spec.add_dependency "oily_png", "~> 1.2.0"
26
+
21
27
  end
@@ -1,5 +1,26 @@
1
+ require "oily_png"
2
+ require "tempfile"
3
+ require "open-uri"
4
+ require "cocaine"
5
+ require "chunky_png_patch/color"
6
+
1
7
  require "camalian/version"
8
+ require "camalian/color"
9
+ require "camalian/palette"
10
+ require "camalian/image"
2
11
 
3
12
  module Camalian
4
- # Your code goes here...
13
+ class << self
14
+ def options
15
+ convert = `which convert`.strip
16
+ @options ||= {
17
+ :image_magick_path => convert.length > 0 ? convert : '/usr/bin/convert',
18
+ :color_count => 8,
19
+ }
20
+ end
21
+
22
+ def load(image_path)
23
+ Image.new(image_path)
24
+ end
25
+ end
5
26
  end
@@ -0,0 +1,98 @@
1
+ module Camalian
2
+ class Color
3
+
4
+ attr_reader :r, :g, :b, :h, :s, :l, :hsv
5
+
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
13
+ end
14
+
15
+ def to_s
16
+ "red=#{r} green=#{g} blue=#{b} hue=#{h} saturation=#{s} lightness=#{l}"
17
+ end
18
+
19
+ def to_hex
20
+ "##{r.to_s(16).rjust(2, '0')}#{g.to_s(16).rjust(2, '0')}#{b.to_s(16).rjust(2, '0')}"
21
+ end
22
+
23
+ def distance(color)
24
+ [(self.h - color.h) % 360, (color.h - self.h) % 360].min
25
+ end
26
+
27
+ def extract_rgb(color_hash)
28
+ color_hash = color_hash[0..6]
29
+ color_hash = color_hash[1..6] if color_hash[0] == '#'
30
+ r = color_hash[0..1].to_i(16)
31
+ g = color_hash[2..3].to_i(16)
32
+ b = color_hash[4..5].to_i(16)
33
+ [r, g, b]
34
+ end
35
+
36
+ private
37
+
38
+ def build_components(r,g,b)
39
+ @r = r
40
+ @g = g
41
+ @b = b
42
+
43
+ ri = @r / 255.0
44
+ gi = @g / 255.0
45
+ bi = @b / 255.0
46
+
47
+ cmax = [ri, gi, bi].max
48
+ cmin = [ri, gi, bi].min
49
+ delta = cmax - cmin
50
+
51
+ @l = (cmax + cmin) / 2.0
52
+
53
+ if delta == 0
54
+ @h = 0
55
+ elsif cmax == ri
56
+ @h = 60 * (((gi - bi) / delta) % 6)
57
+ elsif cmax == gi
58
+ @h = 60 * (((bi - ri)/ delta) + 2)
59
+ elsif cmax == bi
60
+ @h = 60 * (((ri - gi)/ delta) + 4)
61
+ end
62
+
63
+ if (delta == 0)
64
+ @s = 0
65
+ else
66
+ @s = delta / ( 1 - (2*@l -1).abs )
67
+ end
68
+
69
+ @h = @h.round(2)
70
+ @s = (@s * 100).round(2)
71
+ @l = (@l * 100).round(2)
72
+
73
+ # HSV Calculation
74
+ # Hue calculation
75
+ if delta == 0
76
+ @hsv = [0]
77
+ elsif cmax == ri
78
+ @hsv = [60 * (((gi - bi) / delta) % 6)]
79
+ elsif cmax == gi
80
+ @hsv = [60 * (((bi - ri)/ delta) + 2)]
81
+ elsif cmax == bi
82
+ @hsv = [60 * (((ri - gi)/ delta) + 4)]
83
+ end
84
+
85
+ # Saturation calculation
86
+ if (cmax == 0)
87
+ @hsv << 0
88
+ else
89
+ @hsv << delta / cmax
90
+ end
91
+
92
+ # Value calculation
93
+ @hsv << cmax
94
+
95
+ @hsv = [@hsv[0].round(2), (@hsv[1] * 100).round(2), (@hsv[2] * 100).round(2)]
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,36 @@
1
+ require 'rmagick'
2
+
3
+ module Camalian
4
+ class Image
5
+ attr_accessor :src_file_path
6
+
7
+ def initialize(file_path)
8
+ @src_file_path = file_path
9
+ end
10
+
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
21
+ 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 / 255 if s / 255 > 0 # not all ImageMagicks are created equal....
29
+ s
30
+ }
31
+ colors << Color.new(c[0],c[1],c[2])
32
+ end
33
+ return colors.uniq(&:to_hex)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module Camalian
2
+ class Palette < Array
3
+
4
+ def sort_by_lightness
5
+ Palette.new(self.sort_by { |a| a.l }.reverse)
6
+ end
7
+
8
+ def sort_by_hue
9
+ Palette.new(self.sort_by { |a| a.h }.reverse)
10
+ end
11
+
12
+ def sort_similar_colors
13
+ Palette.new(self.sort_by { |a| a.hsv })
14
+ end
15
+
16
+ def sort_by_saturation
17
+ Palette.new(self.sort_by { |a| a.s }.reverse)
18
+ end
19
+
20
+ def light_colors(limit1, limit2)
21
+ min = [limit1, limit2].min
22
+ max = [limit1, limit2].max
23
+ table = self.dup
24
+ Palette.new(table.delete_if { |color| color.l > max or color.l < min })
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Camalian
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,14 @@
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
Binary file
@@ -0,0 +1,29 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/spec'
3
+ require 'camalian'
4
+
5
+ describe Camalian::Color do
6
+ before do
7
+ @color = Camalian::Color.new(120,255,30)
8
+ end
9
+
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
+ end
14
+
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]
17
+ end
18
+
19
+ it "hsv color components must " do
20
+ @color.hsv.map(&:to_i).must_equal [96, 88, 100]
21
+ end
22
+ end
23
+
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
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/spec'
3
+ require 'camalian'
4
+
5
+ describe Camalian::Image do
6
+
7
+ end
8
+
9
+ describe Camalian::Palette do
10
+ before do
11
+ @image = Camalian::load( File.join( File.dirname(__FILE__), 'assets/palette.png'))
12
+ @palette = @image.prominent_colors(15)
13
+ end
14
+
15
+ describe "palette with 15 colors extracted" do
16
+ it "must have 15 colors" do
17
+ @palette.size.must_equal 15
18
+ end
19
+
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
+ end
23
+
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
+ end
27
+ end
28
+ end
metadata CHANGED
@@ -1,16 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: camalian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 0.0.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Nazar Hussain
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-09-12 00:00:00.000000000 Z
13
- dependencies: []
11
+ date: 2015-10-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cocaine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rmagick
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.15.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.15.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: oily_png
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.2.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.0
14
55
  description: Library used to deal with colors and images
15
56
  email:
16
57
  - nazarhussain@gmail.com
@@ -18,38 +59,48 @@ executables: []
18
59
  extensions: []
19
60
  extra_rdoc_files: []
20
61
  files:
21
- - .gitignore
62
+ - ".gitignore"
22
63
  - Gemfile
23
64
  - LICENSE.txt
24
65
  - README.md
25
66
  - Rakefile
26
67
  - camalian.gemspec
27
68
  - lib/camalian.rb
69
+ - lib/camalian/color.rb
70
+ - lib/camalian/image.rb
71
+ - lib/camalian/palette.rb
28
72
  - lib/camalian/version.rb
29
- homepage: http://www.nazarhussain.com
73
+ - lib/chunky_png_patch/color.rb
74
+ - test/assets/palette.png
75
+ - test/test_color.rb
76
+ - test/test_palette.rb
77
+ homepage: https://github.com/nazarhussain/camalian
30
78
  licenses:
31
79
  - MIT
80
+ metadata: {}
32
81
  post_install_message:
33
82
  rdoc_options: []
34
83
  require_paths:
35
84
  - lib
36
85
  required_ruby_version: !ruby/object:Gem::Requirement
37
- none: false
38
86
  requirements:
39
- - - ! '>='
87
+ - - ">="
40
88
  - !ruby/object:Gem::Version
41
89
  version: '0'
42
90
  required_rubygems_version: !ruby/object:Gem::Requirement
43
- none: false
44
91
  requirements:
45
- - - ! '>='
92
+ - - ">="
46
93
  - !ruby/object:Gem::Version
47
94
  version: '0'
48
- requirements: []
95
+ requirements:
96
+ - ImageMagick
49
97
  rubyforge_project:
50
- rubygems_version: 1.8.23
98
+ rubygems_version: 2.4.5
51
99
  signing_key:
52
- specification_version: 3
100
+ specification_version: 4
53
101
  summary: Library used to deal with colors and images. You can extract colors from
54
102
  images.
55
- test_files: []
103
+ test_files:
104
+ - test/assets/palette.png
105
+ - test/test_color.rb
106
+ - test/test_palette.rb