camalian 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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