presto 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9124e378a7b3b0f59475c54788e8824253fcbf9e
4
+ data.tar.gz: dda68438585b0fb4a1c55d2195b72725de6f2ba3
5
+ SHA512:
6
+ metadata.gz: 9f6f23a0791b28f5c8f0fe962d76abbd81d5ce8b5467c8c79002d3fc7f0871d8c15b46113867caca7b43561a0735c651992c8a17ab8bd647e150de4c0bd3d816
7
+ data.tar.gz: e120f3060c2a3a97f2652d2e9d5097ffde3ac0b9dd7d071c9ccc7f3edb6673b437b042317c0691caef221d9eb492c60b9441e14a9b4301673655d00df42acda4
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ spec/processed_images
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in presto.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :minitest, :all_on_start => false do
5
+ # with Minitest::Spec
6
+ watch(%r{^spec/(.*)_spec\.rb})
7
+ watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
+ watch(%r{^spec/spec_helper\.rb}) { 'spec' }
9
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Erik Lott
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Presto
2
+
3
+ Presto allows you to quickly manipulate images in Ruby with minimal
4
+ effort. It is currently a wrapper for the MiniMagick DSL.
5
+
6
+ Tested on the following Rubies: MRI 2.0.0.
7
+
8
+ ## Installation
9
+
10
+ Add the gem to your Gemfile:
11
+
12
+ gem 'presto'
13
+
14
+
15
+ Since Presto is a wrapper for the [MiniMagick](https://github.com/minimagick/minimagick) gem, it will also need to be included in your gemfile.
16
+
17
+ ## Usage
18
+
19
+ Require the Presto mini_magick extension after mini_magick:
20
+
21
+ require 'mini_magick'
22
+ require 'presto/mini_magick'
23
+
24
+ Open and manipulate images using MiniMagick and the new **presto** method
25
+
26
+ image = MiniMagick::Image.open("input.jpg")
27
+ image.presto(w:500, h:200, fit:'crop', q:75, fm:'jpg', bg:'e2e2e2')
28
+ image.write "output.jpg"
29
+
30
+ ## Api
31
+
32
+ ### w, h
33
+ The width and height in pixels of the output image.
34
+
35
+ If only one dimension is specified, the other dimension will be calculated according to the aspect ratio of the input image.
36
+
37
+ ### fit
38
+ Controls how the image is transformed to reach the target dimensions. Possible values are:
39
+
40
+ - **clip** (default): Resize the image to fit within the target dimensions while maintaining the aspect ratio.
41
+ - **crop**: Resize the image to fill the target dimensions, and crop, removing any portion of the image laying outside of the target dimensions.
42
+ - **fill**: Resize the image to fit within the target dimensions, and fill the remaining whitespace with the assigned background color.
43
+ - **scale**: Scale the image to the target dimensions, and disregard the image's aspect ratio.
44
+ - **max**: Resize the image to fit within the target dimensions, if it is larger. This option will not resize an image if it is already equal to or less than the target dimensions.
45
+
46
+ ### bg (background)
47
+ Assigns the background color to use when excess space or transparency is encountered. The hexidecimal color can be assigned in any of the following formats:
48
+
49
+ - **3-Value RGB**: F00 (red)
50
+ - **6-Value RRGGBB**: 00FF00 (green)
51
+ - **8-Value RRGGBBAA**: FFFFFF00 (transparent white)
52
+
53
+
54
+ ### fm (format)
55
+ Sets the format of the output image. Valid values are **jpg** or **png**.
56
+
57
+ ### q (quality)
58
+ A numeric value between 1 (worst) and 100 (best) representing the quality of the output image. Only applies to jpg format images.
59
+
60
+
61
+ ## Contributing
62
+
63
+ 1. Fork it
64
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
65
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
66
+ 4. Push to the branch (`git push origin my-new-feature`)
67
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,14 @@
1
+ module Presto
2
+ class Configuration
3
+
4
+ attr_accessor :max_width, :min_width, :max_height, :min_height, :extension_white_list
5
+
6
+ def initialize
7
+ self.max_width = 2000
8
+ self.min_width = 1
9
+ self.max_height = 2000
10
+ self.min_height = 1
11
+ self.extension_white_list = %w(jpg png)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ module Presto
2
+ class Dimensions < Struct.new(:width, :height)
3
+ def self.resize from_w, from_h, to_w=nil, to_h=nil
4
+ if to_w && to_h
5
+ w = to_w
6
+ h = to_h
7
+ elsif to_w
8
+ w = to_w
9
+ scale_x = to_w / from_w.to_f
10
+ h = (scale_x * from_h).round
11
+ elsif to_h
12
+ h = to_h
13
+ scale_y = to_h / from_h.to_f
14
+ w = (scale_y * from_w).round
15
+ else
16
+ w = from_w
17
+ h = from_h
18
+ end
19
+
20
+ new(w, h)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ module Presto
2
+ class Errors < ::Hash
3
+ ATTRIBUTE_JOINER = ' and '.freeze
4
+
5
+ # Adds an error for the given attribute.
6
+ #
7
+ # errors.add(:name, 'is not valid') if name == 'invalid'
8
+ def add(att, msg)
9
+ fetch(att){self[att] = []} << msg
10
+ end
11
+
12
+ # Return the total number of error messages.
13
+ #
14
+ # errors.count # => 3
15
+ def count
16
+ values.inject(0){|m, v| m + v.length}
17
+ end
18
+
19
+ # Return true if there are no error messages, false otherwise.
20
+ def empty?
21
+ count == 0
22
+ end
23
+
24
+ # Returns an array of fully-formatted error messages.
25
+ #
26
+ # errors.full_messages
27
+ # # => ['name is not valid',
28
+ # # 'hometown is not at least 2 letters']
29
+ def full_messages
30
+ inject([]) do |m, kv|
31
+ att, errors = *kv
32
+ errors.each {|e| m << "#{att} #{e}"}
33
+ m
34
+ end
35
+ end
36
+
37
+ # Returns the array of errors for the given attribute, or nil
38
+ # if there are no errors for the attribute.
39
+ #
40
+ # errors.on(:name) # => ['name is not valid']
41
+ # errors.on(:id) # => nil
42
+ def on(att)
43
+ if v = fetch(att, nil) and !v.empty?
44
+ v
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,4 @@
1
+ module Presto
2
+ class PrestoError < StandardError; end
3
+ class InvalidTransformation < PrestoError; end
4
+ end
@@ -0,0 +1,93 @@
1
+ require 'mini_magick'
2
+ require 'presto/transformation'
3
+ require 'presto/dimensions'
4
+
5
+ module Presto
6
+ module MiniMagick
7
+ class Processor
8
+ def self.process image, params={}
9
+ new(params).process(image)
10
+ end
11
+
12
+ attr_reader :params
13
+
14
+ def initialize params={}
15
+ @params = ::Presto::Transformation.new(params).tap{ |t| t.validate! }
16
+ end
17
+
18
+ def process image
19
+ process_fit(image) if params[:w] || params[:h]
20
+ process_format(image) if params[:fm]
21
+ process_quality(image) if params[:q]
22
+ image
23
+ end
24
+
25
+ private
26
+
27
+ def process_fit image
28
+ send("process_#{params[:fit]}_fit", image)
29
+ end
30
+
31
+ def process_crop_fit image
32
+ d = replaced_dimensions(image)
33
+ image.combine_options do |cmd|
34
+ cmd.resize "#{d.width}x#{d.height}^"
35
+ cmd.background params[:bg]
36
+ cmd.gravity 'Center'
37
+ cmd.extent "#{d.width}x#{d.height}"
38
+ end
39
+ end
40
+
41
+ def process_clip_fit image
42
+ d = resized_dimensions(image)
43
+ image.resize "#{d.width}x#{d.height}"
44
+ end
45
+
46
+ def process_scale_fit image
47
+ d = replaced_dimensions(image)
48
+ image.resize "#{d.width}x#{d.height}!"
49
+ end
50
+
51
+ def process_max_fit image
52
+ d = replaced_dimensions(image)
53
+ image.resize "#{d.width}x#{d.height}>"
54
+ end
55
+
56
+ def process_fill_fit image
57
+ d = replaced_dimensions(image)
58
+ image.combine_options do |cmd|
59
+ cmd.resize "#{d.width}x#{d.height}"
60
+ cmd.background params[:bg]
61
+ cmd.gravity 'Center'
62
+ cmd.extent "#{d.width}x#{d.height}"
63
+ end
64
+ end
65
+
66
+ def process_format image
67
+ image.format params[:fm]
68
+ end
69
+
70
+ def process_quality image
71
+ image.quality params[:q]
72
+ end
73
+
74
+ def resized_dimensions image
75
+ ::Presto::Dimensions.resize(image[:width], image[:height], params[:w], params[:h])
76
+ end
77
+
78
+ def replaced_dimensions image
79
+ w = params[:w] || image[:width]
80
+ h = params[:h] || image[:height]
81
+ ::Presto::Dimensions.new w, h
82
+ end
83
+ end
84
+
85
+ module Extension
86
+ def presto params={}
87
+ ::Presto::MiniMagick::Processor.new(params).process(self)
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ ::MiniMagick::Image.send(:include, ::Presto::MiniMagick::Extension)
@@ -0,0 +1,133 @@
1
+ require 'presto'
2
+ require 'presto/exceptions'
3
+ require 'presto/errors'
4
+
5
+ module Presto
6
+ class Transformation
7
+ class Validator
8
+ HEXDECIMAL_ALPHA_REGEX = /^#[a-fA-F0-9]{8}$/
9
+ HEXDECIMAL_LONG_REGEX = /^#[a-fA-F0-9]{6}$/
10
+ HEXDECIMAL_SHORT_REGEX = /^#[a-fA-F0-9]{3}$/
11
+
12
+ FIT_TYPES = %w(clip crop scale fill max).freeze
13
+ QUALITY_MAX = 100
14
+ QUALITY_MIN = 1
15
+
16
+ attr_reader :record, :errors
17
+
18
+ def initialize record
19
+ @record = record
20
+ end
21
+
22
+ def valid?
23
+ validate
24
+ errors.empty?
25
+ end
26
+
27
+ def validate!
28
+ raise(::Presto::InvalidTransformation, errors.full_messages.join(", ")) unless valid?
29
+ true
30
+ end
31
+
32
+ private
33
+
34
+ def validate
35
+ @errors = Errors.new
36
+ validate_width_max_size! unless record.w.nil?
37
+ validate_width_min_size! unless record.w.nil?
38
+ validate_height_max_size! unless record.h.nil?
39
+ validate_height_min_size! unless record.h.nil?
40
+ validate_fit_presence!
41
+ validate_fit_inclusion!
42
+ validate_bg_format! unless record.bg.nil?
43
+ validate_format_inclusion! unless record.fm.nil?
44
+ validate_quality_max_size! unless record.q.nil?
45
+ validate_quality_min_size! unless record.q.nil?
46
+ end
47
+
48
+ def validate_width_max_size!
49
+ if record.w > max_width
50
+ errors.add(:w, "must be equal to or less than #{max_width}")
51
+ end
52
+ end
53
+
54
+ def validate_width_min_size!
55
+ if record.w < min_width
56
+ errors.add(:w, "must be equal to or greater than #{min_width}")
57
+ end
58
+ end
59
+
60
+ def validate_height_max_size!
61
+ if record.h > max_height
62
+ errors.add(:h, "must be equal to or less than #{max_height}")
63
+ end
64
+ end
65
+
66
+ def validate_height_min_size!
67
+ if record.h < min_height
68
+ errors.add(:h, "must be equal to or greater than #{min_height}")
69
+ end
70
+ end
71
+
72
+ def validate_fit_presence!
73
+ if record.fit.nil? || record.fit.empty?
74
+ errors.add(:fit, "can't be blank")
75
+ end
76
+ end
77
+
78
+ def validate_fit_inclusion!
79
+ unless FIT_TYPES.include?(record.fit)
80
+ errors.add(:fit, "is not valid")
81
+ end
82
+ end
83
+
84
+ def validate_bg_format!
85
+ unless record.bg =~ HEXDECIMAL_LONG_REGEX || record.bg =~ HEXDECIMAL_SHORT_REGEX || record.bg =~ HEXDECIMAL_ALPHA_REGEX
86
+ errors.add(:bg, "is not valid")
87
+ end
88
+ end
89
+
90
+ def validate_format_inclusion!
91
+ unless extension_white_list.include?(record.fm)
92
+ errors.add(:fm, "is not valid")
93
+ end
94
+ end
95
+
96
+ def validate_quality_max_size!
97
+ if record.q > QUALITY_MAX
98
+ errors.add(:q, "must be equal to or less than #{QUALITY_MAX}")
99
+ end
100
+ end
101
+
102
+ def validate_quality_min_size!
103
+ if record.q < QUALITY_MIN
104
+ errors.add(:q, "must be equal to or greater than #{QUALITY_MIN}")
105
+ end
106
+ end
107
+
108
+ def min_width
109
+ config.min_width
110
+ end
111
+
112
+ def max_width
113
+ config.max_width
114
+ end
115
+
116
+ def min_height
117
+ config.min_height
118
+ end
119
+
120
+ def max_height
121
+ config.max_height
122
+ end
123
+
124
+ def extension_white_list
125
+ config.extension_white_list
126
+ end
127
+
128
+ def config
129
+ Presto.configuration
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,33 @@
1
+ require 'presto/transformation/validator'
2
+
3
+ module Presto
4
+ class Transformation
5
+ extend Forwardable
6
+
7
+ def_delegators :validator, :validate!, :valid?
8
+
9
+ attr_reader :w, :h, :fit, :fm, :bg, :q
10
+
11
+ def initialize args={}
12
+ defaults = {:fit => 'clip', :bg => 'ffffff00'}
13
+ params = defaults.merge(args)
14
+
15
+ @bg = "##{params[:bg]}" if params.key?(:bg)
16
+ @fit = params[:fit]
17
+ @fm = params[:fm]
18
+ @h = params[:h].to_i if params.key?(:h)
19
+ @w = params[:w].to_i if params.key?(:w)
20
+ @q = params[:q].to_i if params.key?(:q)
21
+ end
22
+
23
+ def [] val
24
+ send(val)
25
+ end
26
+
27
+ private
28
+
29
+ def validator
30
+ ::Presto::Transformation::Validator.new(self)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module Presto
2
+ VERSION = "0.0.1"
3
+ end
data/lib/presto.rb ADDED
@@ -0,0 +1,17 @@
1
+
2
+ require 'presto/version'
3
+ require 'presto/configuration'
4
+
5
+ module Presto
6
+ class << self
7
+ attr_writer :configuration
8
+
9
+ def configure
10
+ yield(configuration)
11
+ end
12
+
13
+ def configuration
14
+ @configuration ||= ::Presto::Configuration.new
15
+ end
16
+ end
17
+ end
data/presto.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'presto/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "presto"
8
+ spec.version = Presto::VERSION
9
+ spec.authors = ["Erik Lott"]
10
+ spec.email = ["erik.lott@kodio.io"]
11
+ spec.description = %q{Process images with one simple command}
12
+ spec.summary = %q{Perform image transformations with one simple command}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "guard-minitest", "~> 1.0.1"
24
+ spec.add_development_dependency "mocha", "~> 0.14.0"
25
+ spec.add_development_dependency "mini_magick", "~> 3.6.0"
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'presto/configuration'
3
+
4
+ describe Presto::Configuration do
5
+ let(:configuration) { Presto::Configuration.new }
6
+
7
+ it "sets max_width default of 2000" do
8
+ configuration.max_width.must_equal 2000
9
+ end
10
+
11
+ it "sets min_width default of 1" do
12
+ configuration.min_width.must_equal 1
13
+ end
14
+
15
+ it "sets max_height default of 2000" do
16
+ configuration.max_height.must_equal 2000
17
+ end
18
+
19
+ it "sets min_height default of 1" do
20
+ configuration.min_height.must_equal 1
21
+ end
22
+
23
+ it "sets extension_white_list default of 1" do
24
+ configuration.extension_white_list.must_equal %w(jpg png)
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'presto/dimensions'
3
+
4
+ describe Presto::Dimensions do
5
+ describe "::resize" do
6
+ describe "when target width and height assigned" do
7
+ it "returns target width and height" do
8
+ d = ::Presto::Dimensions.resize(123, 234, 345, 456)
9
+ d.width.must_equal 345
10
+ d.height.must_equal 456
11
+ end
12
+ end
13
+
14
+ describe "when only target width assigned" do
15
+ it "returns target width with proportional height" do
16
+ d = ::Presto::Dimensions.resize(100, 250, 300, nil)
17
+ d.width.must_equal 300
18
+ d.height.must_equal 750
19
+ end
20
+ end
21
+
22
+ describe "when only target height assigned" do
23
+ it "returns target height with proportional width" do
24
+ d = ::Presto::Dimensions.resize(100, 250, nil, 500)
25
+ d.width.must_equal 200
26
+ d.height.must_equal 500
27
+ end
28
+ end
29
+
30
+ describe "when target width and height not assigned" do
31
+ it "return original width and height" do
32
+ d = ::Presto::Dimensions.resize(123, 234)
33
+ d.width.must_equal 123
34
+ d.height.must_equal 234
35
+ end
36
+ end
37
+ end
38
+ end
Binary file
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'presto/mini_magick'
3
+
4
+ describe Presto::MiniMagick::Extension do
5
+ it "extends MiniMagick with extension" do
6
+ klass = Class.new
7
+ klass.send(:include, Presto::MiniMagick::Extension)
8
+
9
+ inst = klass.new
10
+ inst.respond_to?(:presto).must_equal true
11
+ end
12
+ end
@@ -0,0 +1,207 @@
1
+ require 'spec_helper'
2
+ require 'presto/mini_magick'
3
+
4
+ describe Presto::MiniMagick::Processor do
5
+ let(:file) { ::File.open(File.expand_path('../../fixtures/images/test.gif', __FILE__)) }
6
+ let(:image) { ::MiniMagick::Image.open(file.path) }
7
+
8
+ describe "#initalize" do
9
+ describe "when params are not valid" do
10
+ it "raises error" do
11
+ e = proc{ Presto::MiniMagick::Processor.new(:fm => 'xml') }.must_raise(::Presto::InvalidTransformation)
12
+ e.message.must_equal 'fm is not valid'
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "#process_crop_fit" do
18
+ describe "w and h assigned" do
19
+ it "resizes image to fill dimensions, and crops overlap" do
20
+ processor = Presto::MiniMagick::Processor.new(:w => 50, :h => 100)
21
+ processor.send(:process_crop_fit, image)
22
+ image[:width].must_equal 50
23
+ image[:height].must_equal 100
24
+
25
+ image.write File.expand_path("../../processed_images/process_crop_fit-w_and_h", __FILE__)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "#process_clip_fit" do
31
+ describe "w and h assigned" do
32
+ it "resizes image to fit within dimensions" do
33
+ processor = Presto::MiniMagick::Processor.new(:w => 50, :h => 50)
34
+ processor.send(:process_clip_fit, image)
35
+ image[:width].must_equal 50
36
+ image[:height].must_equal 20
37
+
38
+ image.write File.expand_path("../../processed_images/process_clip_fit-w_and_h", __FILE__)
39
+ end
40
+ end
41
+
42
+ describe "w assigned" do
43
+ it "resizes image to match width" do
44
+ processor = Presto::MiniMagick::Processor.new(:w => 100)
45
+ processor.send(:process_clip_fit, image)
46
+ image[:width].must_equal 100
47
+ image[:height].must_equal 40
48
+
49
+ image.write File.expand_path("../../processed_images/process_clip_fit-w", __FILE__)
50
+ end
51
+ end
52
+
53
+ describe "h assigned" do
54
+ it "resizes image to match height" do
55
+ processor = Presto::MiniMagick::Processor.new(:h => 100)
56
+ processor.send(:process_clip_fit, image)
57
+ image[:width].must_equal 250
58
+ image[:height].must_equal 100
59
+
60
+ image.write File.expand_path("../../processed_images/process_clip_fit-h", __FILE__)
61
+ end
62
+ end
63
+
64
+ describe "w and h unassigned" do
65
+ it "does nothing" do
66
+ processor = Presto::MiniMagick::Processor.new
67
+ processor.send(:process_clip_fit, image)
68
+ image[:width].must_equal 500
69
+ image[:height].must_equal 200
70
+
71
+ image.write File.expand_path("../../processed_images/process_clip_fit-no_dimensions", __FILE__)
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "#process_scale_fit" do
77
+ describe "w and h assigned" do
78
+ it "scales image to match dimensions" do
79
+ processor = Presto::MiniMagick::Processor.new(:w => 50, :h => 100)
80
+ processor.send(:process_scale_fit, image)
81
+ image[:width].must_equal 50
82
+ image[:height].must_equal 100
83
+
84
+ image.write File.expand_path("../../processed_images/process_scale_fit-w_and_h", __FILE__)
85
+ end
86
+ end
87
+
88
+ describe "w assigned" do
89
+ it "scales image to match width" do
90
+ processor = Presto::MiniMagick::Processor.new(:w => 50)
91
+ processor.send(:process_scale_fit, image)
92
+ image[:width].must_equal 50
93
+ image[:height].must_equal 200
94
+
95
+ image.write File.expand_path("../../processed_images/process_scale_fit-w", __FILE__)
96
+ end
97
+ end
98
+
99
+ describe "h assigned" do
100
+ it "scales image to match height" do
101
+ processor = Presto::MiniMagick::Processor.new(:h => 50)
102
+ processor.send(:process_scale_fit, image)
103
+ image[:width].must_equal 500
104
+ image[:height].must_equal 50
105
+
106
+ image.write File.expand_path("../../processed_images/process_scale_fit-h", __FILE__)
107
+ end
108
+ end
109
+ end
110
+
111
+ describe "#process_max_fit" do
112
+ describe "w and h assigned" do
113
+ it "resizes large image to fit within dimensions" do
114
+ processor = Presto::MiniMagick::Processor.new(:w => 250, :h => 500)
115
+ processor.send(:process_max_fit, image)
116
+ image[:width].must_equal 250
117
+ image[:height].must_equal 100
118
+
119
+ image.write File.expand_path("../../processed_images/process_max_fit-w_and_h_1", __FILE__)
120
+ end
121
+
122
+ it "does not resize if smaller than dimensions" do
123
+ processor = Presto::MiniMagick::Processor.new(:w => 1000, :h => 1200)
124
+ processor.send(:process_max_fit, image)
125
+ image[:width].must_equal 500
126
+ image[:height].must_equal 200
127
+
128
+ image.write File.expand_path("../../processed_images/process_max_fit-w_and_h_2", __FILE__)
129
+ end
130
+ end
131
+
132
+ describe "w assigned" do
133
+ it "resizes wide image to fit within width" do
134
+ processor = Presto::MiniMagick::Processor.new(:w => 250)
135
+ processor.send(:process_max_fit, image)
136
+ image[:width].must_equal 250
137
+ image[:height].must_equal 100
138
+
139
+ image.write File.expand_path("../../processed_images/process_max_fit-w_1", __FILE__)
140
+ end
141
+
142
+ it "does not adjust image if less wide than width" do
143
+ processor = Presto::MiniMagick::Processor.new(:w => 600)
144
+ processor.send(:process_max_fit, image)
145
+ image[:width].must_equal 500
146
+ image[:height].must_equal 200
147
+
148
+ image.write File.expand_path("../../processed_images/process_max_fit-w_2", __FILE__)
149
+ end
150
+ end
151
+
152
+ describe "h assigned" do
153
+ it "reduces tall image to fit within height" do
154
+ processor = Presto::MiniMagick::Processor.new(:h => 50)
155
+ processor.send(:process_max_fit, image)
156
+ image[:width].must_equal 125
157
+ image[:height].must_equal 50
158
+
159
+ image.write File.expand_path("../../processed_images/process_max_fit-h_1", __FILE__)
160
+ end
161
+
162
+ it "does not adjust image if less wide than width" do
163
+ processor = Presto::MiniMagick::Processor.new(:h => 300)
164
+ processor.send(:process_max_fit, image)
165
+ image[:width].must_equal 500
166
+ image[:height].must_equal 200
167
+
168
+ image.write File.expand_path("../../processed_images/process_max_fit-h_2", __FILE__)
169
+ end
170
+ end
171
+ end
172
+
173
+ describe "#process_fill_fit" do
174
+ describe "w and h assigned" do
175
+ it "resizes image to fit within dimensions, applies background to dimension" do
176
+ processor = Presto::MiniMagick::Processor.new(:w => 400, :h => 400, :bg => 'F00')
177
+ processor.send(:process_fill_fit, image)
178
+ image[:width].must_equal 400
179
+ image[:height].must_equal 400
180
+
181
+ image.write File.expand_path("../../processed_images/process_fill_fit-w_h", __FILE__)
182
+ end
183
+ end
184
+ end
185
+
186
+ describe "#process_format" do
187
+ it "sets image format" do
188
+ processor = Presto::MiniMagick::Processor.new(:fm => 'png')
189
+ processor.send(:process_format, image)
190
+ image[:format].must_equal 'PNG'
191
+ end
192
+ end
193
+
194
+ describe "#process_quality" do
195
+ it "sets image quality" do
196
+ img1 = ::MiniMagick::Image.open(file.path)
197
+ processor = Presto::MiniMagick::Processor.new(:q => 10, :fm => 'jpg', :w => 50)
198
+ processor.process img1
199
+ img1.write File.expand_path("../../processed_images/process_quality-10", __FILE__)
200
+
201
+ img2 = ::MiniMagick::Image.open(file.path)
202
+ processor = Presto::MiniMagick::Processor.new(:q => 100, :fm => 'jpg', :w => 50)
203
+ processor.process img2
204
+ img2.write File.expand_path("../../processed_images/process_quality-100", __FILE__)
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'presto'
3
+
4
+ describe Presto do
5
+ describe "::configuration" do
6
+ it "returns configuration instance" do
7
+ Presto.configuration.must_be_instance_of Presto::Configuration
8
+ end
9
+
10
+ it "memoizes configuration instance" do
11
+ config_inst = Presto.configuration
12
+ config_inst_2 = Presto.configuration
13
+ config_inst.object_id.must_equal config_inst_2.object_id
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,2 @@
1
+ require 'minitest/autorun'
2
+ require 'mocha/setup'
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+ require 'presto/transformation/validator'
3
+
4
+ describe Presto::Transformation::Validator do
5
+ let(:w) { 100 }
6
+ let(:h) { 200 }
7
+ let(:fit) { 'clip' }
8
+ let(:bg) { '#fffddd' }
9
+ let(:fm){ 'jpg' }
10
+ let(:q){ 92 }
11
+ let(:transformation) { stub(:w => w, :h => h, :fit => fit, :bg => bg, :fm => fm, :q => q) }
12
+ let(:validator){ Presto::Transformation::Validator.new(transformation) }
13
+
14
+ describe "#validate!" do
15
+ describe "when valid" do
16
+ it "returns true" do
17
+ validator.validate!.must_equal true
18
+ end
19
+ end
20
+
21
+ describe "when w is nil" do
22
+ let(:w) { nil }
23
+
24
+ it "does not raise error" do
25
+ validator.validate!.must_equal true
26
+ end
27
+ end
28
+
29
+ describe "when w is greater than max w" do
30
+ let(:w) { Presto.configuration.max_width + 1 }
31
+
32
+ it "raises error" do
33
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
34
+ e.message.must_match "w must be equal to or less than"
35
+ end
36
+ end
37
+
38
+ describe "when w is less than min w" do
39
+ let(:w) { Presto.configuration.min_width - 1 }
40
+
41
+ it "raises error" do
42
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
43
+ e.message.must_match "w must be equal to or greater than"
44
+ end
45
+ end
46
+
47
+ describe "when h is nil" do
48
+ let(:h) { nil }
49
+
50
+ it "does not raise error" do
51
+ validator.validate!.must_equal true
52
+ end
53
+ end
54
+
55
+ describe "when h is greater than max h" do
56
+ let(:h) { Presto.configuration.max_height + 1 }
57
+
58
+ it "raises error" do
59
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
60
+ e.message.must_match "h must be equal to or less than"
61
+ end
62
+ end
63
+
64
+ describe "when h is less than min h" do
65
+ let(:h) { Presto.configuration.min_height - 1 }
66
+
67
+ it "raises error" do
68
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
69
+ e.message.must_match "h must be equal to or greater than"
70
+ end
71
+ end
72
+
73
+ describe "when fit is nil" do
74
+ let(:fit) { nil }
75
+
76
+ it "raises error" do
77
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
78
+ e.message.must_match "fit can't be blank"
79
+ end
80
+ end
81
+
82
+ describe "when fit is invalid" do
83
+ let(:fit) { 'blah' }
84
+
85
+ it "raises error" do
86
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
87
+ e.message.must_match "fit is not valid"
88
+ end
89
+ end
90
+
91
+ describe "when bg is wrong formal" do
92
+ let(:bg) { 'fhff' }
93
+
94
+ it "raises error" do
95
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
96
+ e.message.must_match "bg is not valid"
97
+ end
98
+ end
99
+
100
+ describe "when fm is invalid" do
101
+ let(:fm) { 'tif' }
102
+
103
+ it "raises error" do
104
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
105
+ e.message.must_match "fm is not valid"
106
+ end
107
+ end
108
+
109
+ describe "when q is nil" do
110
+ let(:q) { nil }
111
+
112
+ it "does not raise error" do
113
+ validator.validate!.must_equal true
114
+ end
115
+ end
116
+
117
+ describe "when q is greater than max q" do
118
+ let(:q) { ::Presto::Transformation::Validator::QUALITY_MAX + 1 }
119
+
120
+ it "raises error" do
121
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
122
+ e.message.must_match "q must be equal to or less than #{::Presto::Transformation::Validator::QUALITY_MAX}"
123
+ end
124
+ end
125
+
126
+ describe "when q is less than min q" do
127
+ let(:q) { ::Presto::Transformation::Validator::QUALITY_MIN - 1 }
128
+
129
+ it "raises error" do
130
+ e = proc { validator.validate! }.must_raise(Presto::InvalidTransformation)
131
+ e.message.must_match "q must be equal to or greater than #{::Presto::Transformation::Validator::QUALITY_MIN}"
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'presto/transformation'
3
+
4
+ describe Presto::Transformation do
5
+ it "sets default fit" do
6
+ Presto::Transformation.new.fit.must_equal 'clip'
7
+ end
8
+
9
+ it "sets default bg" do
10
+ Presto::Transformation.new.bg.must_equal '#ffffff00'
11
+ end
12
+
13
+ it "coerses w to integer" do
14
+ Presto::Transformation.new(:w => '123').w.must_equal 123
15
+ end
16
+
17
+ it "coerses h to integer" do
18
+ Presto::Transformation.new(:h => '123').h.must_equal 123
19
+ end
20
+
21
+ it "coerses bg to hexdec format" do
22
+ Presto::Transformation.new(:bg => 'eee').bg.must_equal '#eee'
23
+ end
24
+
25
+ it "coerses q to integer" do
26
+ Presto::Transformation.new(:q => '50').q.must_equal 50
27
+ end
28
+
29
+ it "can access method via hash syntax" do
30
+ trans = Presto::Transformation.new(:h => 123)
31
+ trans[:h].must_equal 123
32
+ trans['h'].must_equal 123
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: presto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Erik Lott
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.14.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.14.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: mini_magick
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 3.6.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 3.6.0
83
+ description: Process images with one simple command
84
+ email:
85
+ - erik.lott@kodio.io
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - Gemfile
92
+ - Guardfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - lib/presto.rb
97
+ - lib/presto/configuration.rb
98
+ - lib/presto/dimensions.rb
99
+ - lib/presto/errors.rb
100
+ - lib/presto/exceptions.rb
101
+ - lib/presto/mini_magick.rb
102
+ - lib/presto/transformation.rb
103
+ - lib/presto/transformation/validator.rb
104
+ - lib/presto/version.rb
105
+ - presto.gemspec
106
+ - spec/configuration_spec.rb
107
+ - spec/dimensions_spec.rb
108
+ - spec/fixtures/images/test.gif
109
+ - spec/mini_magick/extension_spec.rb
110
+ - spec/mini_magick/processor_spec.rb
111
+ - spec/presto_spec.rb
112
+ - spec/spec_helper.rb
113
+ - spec/transformation/validator_spec.rb
114
+ - spec/transformation_spec.rb
115
+ homepage: ''
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.0.7
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: Perform image transformations with one simple command
139
+ test_files:
140
+ - spec/configuration_spec.rb
141
+ - spec/dimensions_spec.rb
142
+ - spec/fixtures/images/test.gif
143
+ - spec/mini_magick/extension_spec.rb
144
+ - spec/mini_magick/processor_spec.rb
145
+ - spec/presto_spec.rb
146
+ - spec/spec_helper.rb
147
+ - spec/transformation/validator_spec.rb
148
+ - spec/transformation_spec.rb