diff --git a/.rspec b/.rspec index 4e1e0d2..83e16f8 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ --color +--require spec_helper diff --git a/Gemfile.lock b/Gemfile.lock index e24a4fd..1d39ad9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,68 +6,73 @@ PATH addressable (~> 2.2) dragonfly (~> 0.9.14) httparty (~> 0.13) + rmagick (~> 2.15.4) sinatra (~> 1.2) GEM remote: https://rubygems.org/ specs: - activesupport (4.1.8) - i18n (~> 0.6, >= 0.6.9) + activesupport (4.2.5.1) + i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) - thread_safe (~> 0.1) + thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.3.6) - crack (0.4.2) + addressable (2.4.0) + crack (0.4.3) safe_yaml (~> 1.0.0) diff-lcs (1.2.5) - dotenv (1.0.2) + dotenv (2.1.0) dragonfly (0.9.15) multi_json (~> 1.0) rack - fastimage (1.6.6) + fastimage (1.8.1) addressable (~> 2.3, >= 2.3.5) - httparty (0.13.3) + hashdiff (0.2.3) + httparty (0.13.7) json (~> 1.8) multi_xml (>= 0.5.2) - i18n (0.6.11) - json (1.8.1) - minitest (5.4.3) - multi_json (1.10.1) + i18n (0.7.0) + json (1.8.3) + minitest (5.8.4) + multi_json (1.11.2) multi_xml (0.5.5) - newrelic_rpm (3.9.8.273) - rack (1.5.2) - rack-cache (1.2) + newrelic_rpm (3.14.2.312) + rack (1.6.4) + rack-cache (1.6.0) rack (>= 0.4) rack-protection (1.5.3) rack - rack-test (0.6.2) + rack-test (0.6.3) rack (>= 1.0) - rake (10.4.2) - rspec (3.1.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) - rspec-core (3.1.7) - rspec-support (~> 3.1.0) - rspec-expectations (3.1.2) + rake (10.5.0) + rmagick (2.15.4) + rspec (3.4.0) + rspec-core (~> 3.4.0) + rspec-expectations (~> 3.4.0) + rspec-mocks (~> 3.4.0) + rspec-core (3.4.2) + rspec-support (~> 3.4.0) + rspec-expectations (3.4.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-mocks (3.4.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.1.0) - rspec-mocks (3.1.3) - rspec-support (~> 3.1.0) - rspec-support (3.1.2) + rspec-support (~> 3.4.0) + rspec-support (3.4.1) safe_yaml (1.0.4) - sinatra (1.4.5) - rack (~> 1.4) + sinatra (1.4.7) + rack (~> 1.5) rack-protection (~> 1.4) - tilt (~> 1.3, >= 1.3.4) - thread_safe (0.3.4) - tilt (1.4.1) + tilt (>= 1.3, < 3) + thread_safe (0.3.5) + tilt (2.0.2) tzinfo (1.2.2) thread_safe (~> 0.1) - webmock (1.20.4) + webmock (1.22.6) addressable (>= 2.3.6) crack (>= 0.3.2) + hashdiff PLATFORMS ruby @@ -82,3 +87,6 @@ DEPENDENCIES rake rspec webmock + +BUNDLED WITH + 1.11.2 diff --git a/lib/dragonfly/data_storage/remote_data_store.rb b/lib/dragonfly/data_storage/remote_data_store.rb index 578d6b2..3aceaeb 100644 --- a/lib/dragonfly/data_storage/remote_data_store.rb +++ b/lib/dragonfly/data_storage/remote_data_store.rb @@ -1,6 +1,9 @@ require 'httparty' require 'uri' +# TODO figure out how to automatically set cert path +HTTParty::Basement.default_options.update(verify: false) + module Dragonfly module DataStorage #class Forbidden < StandardError; end diff --git a/lib/magickly.rb b/lib/magickly.rb index ff29695..24db9a8 100644 --- a/lib/magickly.rb +++ b/lib/magickly.rb @@ -5,6 +5,7 @@ require 'sinatra/base' require 'addressable/uri' require 'dragonfly' +require 'rmagick' Dir["#{File.dirname(__FILE__)}/dragonfly/**/*.rb"].each {|file| require file } Dir["#{File.dirname(__FILE__)}/magickly/*.rb"].each {|file| require file } diff --git a/lib/magickly/rmagick_helper.rb b/lib/magickly/rmagick_helper.rb new file mode 100644 index 0000000..661569c --- /dev/null +++ b/lib/magickly/rmagick_helper.rb @@ -0,0 +1,16 @@ +module Magickly + module RmagickHelper + # http://blog.kellishaver.com/image-color-analysis-with-rmagick/ + def self.to_hex_val(color_int) + sprintf('%02x', color_int / 256).upcase + end + + def self.to_hex(pixel) + [ + to_hex_val(pixel.red), + to_hex_val(pixel.green), + to_hex_val(pixel.blue) + ].join + end + end +end diff --git a/lib/shortcuts.rb b/lib/shortcuts.rb index a1b7d1e..b13b109 100644 --- a/lib/shortcuts.rb +++ b/lib/shortcuts.rb @@ -84,13 +84,16 @@ c.analyser.add :color_palette do |temp_object, num_colors| num_colors = num_colors.blank? ? Magickly::DEFAULT_PALETTE_COLOR_COUNT : num_colors.to_i - output = `convert #{temp_object.path} -resize 600x600 -colors #{num_colors} -format %c -depth 8 histogram:info:-` - palette = [] - output.scan(/\s+(\d+):[^\n]+#([0-9A-Fa-f]{6})/) do |count, hex| - palette << { :count => count.to_i, :hex => hex } + img = Magick::Image.from_blob(temp_object.data).first + histogram = img.quantize(num_colors).color_histogram + + histogram.map do |pixel, frequency| + { + :count => frequency, + :hex => Magickly::RmagickHelper.to_hex(pixel) + } end - palette end c.job :output do |val| diff --git a/magickly.gemspec b/magickly.gemspec index 2ea2890..4b760c2 100644 --- a/magickly.gemspec +++ b/magickly.gemspec @@ -22,6 +22,7 @@ Gem::Specification.new do |s| s.add_dependency('sinatra', ['~> 1.2']) s.add_dependency('dragonfly', ['~> 0.9.14']) + s.add_dependency('rmagick', ['~> 2.15.4']) s.add_dependency('addressable', ['~> 2.2']) s.add_dependency('httparty', ['~> 0.13']) s.add_dependency('activesupport', ['>= 2.0.0', '< 5']) diff --git a/spec/requests/magickly_app_spec.rb b/spec/requests/magickly_app_spec.rb index b321ce7..4b75c12 100644 --- a/spec/requests/magickly_app_spec.rb +++ b/spec/requests/magickly_app_spec.rb @@ -76,7 +76,7 @@ def get_image(uri) expect(a_request(:get, @image_url)).to have_been_made.once expect(last_response.status).to eq(200) - expect(FastImage.size(file)[0]).to eq(width) + expect(file).to have_width(width) end it "outputs an image in a new format" do @@ -101,7 +101,7 @@ def get_image(uri) file = get_image "/?src=#{@image_url}&#{shortcut}=true" expect(last_response.status).to eq(200) - expect(FastImage.size(file)[0]).to eq width + expect(file).to have_width(width) end it "should use my Dragonfly shortcut with one argument" do @@ -117,7 +117,7 @@ def get_image(uri) file = get_image "/?src=#{@image_url}&#{shortcut}=#{width}x" expect(last_response.status).to eq(200) - expect(FastImage.size(file)[0]).to eq width + expect(file).to have_width(width) end end @@ -131,7 +131,7 @@ def get_image(uri) expect(a_request(:get, @image_url)).to have_been_made.once expect(last_response.status).to eq(200) - expect(FastImage.size(file)[0]).to eq width + expect(file).to have_width(width) end end @@ -153,7 +153,7 @@ def get_image(uri) expect(a_request(:get, @image_url)).to have_been_made.once expect(last_response.status).to eq(200) - expect(FastImage.size(file)[0]).to eq width + expect(file).to have_width(width) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f3df994..6fa9928 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,7 +8,7 @@ # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. -# Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f} +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f} set :environment, :test diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb new file mode 100644 index 0000000..78d6b48 --- /dev/null +++ b/spec/support/matchers.rb @@ -0,0 +1,11 @@ +RSpec::Matchers.define :have_width do |expected| + match do |file| + expect(FastImage.size(file)[0]).to eq(expected) + end +end + +RSpec::Matchers.define :have_height do |expected| + match do |file| + expect(FastImage.size(file)[1]).to eq(expected) + end +end diff --git a/spec/unit/magickly_spec.rb b/spec/unit/magickly_spec.rb index daf6cc4..1d01775 100644 --- a/spec/unit/magickly_spec.rb +++ b/spec/unit/magickly_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - describe Magickly do describe ".process_src" do it "retrieves an image with no options" do diff --git a/spec/unit/remote_data_store_spec.rb b/spec/unit/remote_data_store_spec.rb index defb225..9c7c526 100644 --- a/spec/unit/remote_data_store_spec.rb +++ b/spec/unit/remote_data_store_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - describe Dragonfly::DataStorage::RemoteDataStore do describe '#retrieve' do it "should successfully make requests" do @@ -37,4 +35,3 @@ end end end - diff --git a/spec/unit/rmagick_helper_spec.rb b/spec/unit/rmagick_helper_spec.rb new file mode 100644 index 0000000..bc4ecae --- /dev/null +++ b/spec/unit/rmagick_helper_spec.rb @@ -0,0 +1,18 @@ +describe Magickly::RmagickHelper do + describe '.to_hex' do + it "converts black correctly" do + pixel = Magick::Pixel.from_color('black') + expect(Magickly::RmagickHelper.to_hex(pixel)).to eq('000000') + end + + it "converts white correctly" do + pixel = Magick::Pixel.from_color('white') + expect(Magickly::RmagickHelper.to_hex(pixel)).to eq('FFFFFF') + end + + it "converts an intermediate color correctly" do + pixel = Magick::Pixel.from_color('aquamarine') + expect(Magickly::RmagickHelper.to_hex(pixel)).to eq('7FFFD4') + end + end +end diff --git a/spec/unit/shortcut_spec.rb b/spec/unit/shortcut_spec.rb index 7306e05..9541187 100644 --- a/spec/unit/shortcut_spec.rb +++ b/spec/unit/shortcut_spec.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - describe "Dragonfly shortcuts" do before do @image_path = File.join(File.dirname(__FILE__), '..', 'support', 'imagemagick.png') @@ -8,7 +6,7 @@ describe :brightness_contrast do it "should throw an error for no arguments" do - expect { @image.brightness_contrast }.to raise_error + expect { @image.brightness_contrast }.to raise_error(ArgumentError) end it "should throw an error for a empty string" do @@ -46,7 +44,7 @@ describe :tilt_shift do it "should throw an error for no coefficient" do - expect { @image.tilt_shift }.to raise_error + expect { @image.tilt_shift }.to raise_error(ArgumentError) end it "should throw an error for a empty string" do