dynamic_image 1.0.4 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/{LICENSE → MIT-LICENSE} +1 -1
- data/README.md +57 -80
- data/Rakefile +7 -30
- data/lib/dynamic_image/belongs_to.rb +22 -0
- data/lib/dynamic_image/controller.rb +94 -0
- data/lib/dynamic_image/digest_verifier.rb +62 -0
- data/lib/dynamic_image/errors.rb +10 -0
- data/lib/dynamic_image/helper.rb +139 -85
- data/lib/dynamic_image/image_sizing.rb +156 -0
- data/lib/dynamic_image/metadata.rb +84 -0
- data/lib/dynamic_image/model/dimensions.rb +95 -0
- data/lib/dynamic_image/model/validations.rb +94 -0
- data/lib/dynamic_image/model.rb +130 -0
- data/lib/dynamic_image/processed_image.rb +119 -0
- data/lib/dynamic_image/railtie.rb +18 -0
- data/lib/dynamic_image/routing.rb +24 -0
- data/lib/dynamic_image/version.rb +5 -0
- data/lib/dynamic_image.rb +14 -71
- data/lib/rails/generators/dynamic_image/resource/resource_generator.rb +74 -0
- metadata +130 -97
- data/VERSION +0 -1
- data/app/controllers/images_controller.rb +0 -79
- data/app/models/image.rb +0 -188
- data/config/routes.rb +0 -16
- data/dynamic_image.gemspec +0 -62
- data/dynamic_image.sublime-project +0 -9
- data/dynamic_image.sublime-workspace +0 -1599
- data/init.rb +0 -1
- data/install.rb +0 -1
- data/lib/binary_storage/active_record_extensions.rb +0 -144
- data/lib/binary_storage/blob.rb +0 -104
- data/lib/binary_storage.rb +0 -28
- data/lib/dynamic_image/active_record_extensions.rb +0 -60
- data/lib/dynamic_image/engine.rb +0 -6
- data/lib/dynamic_image/filterset.rb +0 -79
- data/lib/generators/dynamic_image/USAGE +0 -5
- data/lib/generators/dynamic_image/dynamic_image_generator.rb +0 -38
- data/lib/generators/dynamic_image/templates/migrations/create_images.rb +0 -21
- data/uninstall.rb +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa4635730b705cb0d3d48024139359bc7bbbfef6
|
4
|
+
data.tar.gz: ededec9d42f262502983c22c8c753b8de8498a9b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3558ebbfb2e0f5e2744bbdc028da4e73515134fa88100749bf072af97f61707dfb56a969d31a482d409e24818548dab1cd09207b46a4925552b5d051ce714cb5
|
7
|
+
data.tar.gz: be91b398098093248afd99558fe3101eedd1917193efba2632d36e3617d5929f5c3d1709745e2ddd8427b612b4a7024ad4c148e1e4adcf95044c0feb19564995
|
data/{LICENSE → MIT-LICENSE}
RENAMED
data/README.md
CHANGED
@@ -1,109 +1,86 @@
|
|
1
|
-
# DynamicImage
|
2
|
-
|
3
|
-
DynamicImage is a Rails plugin that simplifies image uploading and processing.
|
4
|
-
No configuration is necessary, as resizing and processing is done on demand and
|
5
|
-
cached rather than on upload.
|
6
|
-
|
7
|
-
Note: This version is currently Rails 3 specific, although the final 1.0
|
8
|
-
version will also be compatible with 2.x.
|
1
|
+
# DynamicImage [![Build Status](https://travis-ci.org/elektronaut/dynamic_image.png)](https://travis-ci.org/elektronaut/dynamic_image) [![Code Climate](https://codeclimate.com/github/elektronaut/dynamic_image.png)](https://codeclimate.com/github/elektronaut/dynamic_image) [![Code Climate](https://codeclimate.com/github/elektronaut/dynamic_image/coverage.png)](https://codeclimate.com/github/elektronaut/dynamic_image)
|
9
2
|
|
3
|
+
Requires Rails 4.1+ and Ruby 1.9.3+.
|
10
4
|
|
11
5
|
## Installation
|
12
6
|
|
13
|
-
|
14
|
-
|
15
|
-
gem install dynamic_image
|
16
|
-
|
17
|
-
Add the gem to your Gemfile:
|
18
|
-
|
19
|
-
gem 'dynamic_image'
|
20
|
-
|
21
|
-
Do the migrations:
|
22
|
-
|
23
|
-
rails generate dynamic_image migrations
|
24
|
-
rake db:migrate
|
25
|
-
|
26
|
-
|
27
|
-
## Getting started
|
7
|
+
Add the gem to your Gemfile and run `bundle install`.
|
28
8
|
|
29
|
-
|
9
|
+
```ruby
|
10
|
+
gem "dynamic_image"
|
11
|
+
```
|
30
12
|
|
31
|
-
|
32
|
-
belongs_to_image :mugshot
|
33
|
-
end
|
13
|
+
Run the `dis:install` generator to set up your storage.
|
34
14
|
|
35
|
-
|
36
|
-
|
15
|
+
```sh
|
16
|
+
bin/rails generate dis:install
|
17
|
+
```
|
37
18
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
<% end %>
|
19
|
+
You can edit the generated initializer to configure your storage, by default it
|
20
|
+
will store files in `db/dis`. See the
|
21
|
+
[Dis](https://github.com/elektronaut/dis) documentation for more
|
22
|
+
information.
|
43
23
|
|
44
|
-
|
45
|
-
new image:
|
24
|
+
## Creating your resource
|
46
25
|
|
47
|
-
|
48
|
-
<%= dynamic_image_tag @user.profile_picture, :size => '64x64' %>
|
49
|
-
<% end %>
|
26
|
+
Run the `dynamic_image:resource` generator to create your resource.
|
50
27
|
|
28
|
+
```sh
|
29
|
+
bin/rails generate dynamic_image:resource image
|
30
|
+
```
|
51
31
|
|
52
|
-
|
32
|
+
This will create an `Image` model and a controller, along with a migration and
|
33
|
+
the necessary routes.
|
53
34
|
|
54
|
-
|
35
|
+
Note that in this case, the route with collide with any static images stored
|
36
|
+
in `public/images`. You can customize the path if you want in the route
|
37
|
+
declaration.
|
55
38
|
|
39
|
+
```ruby
|
40
|
+
image_resources :images, path: "dynamic_images/:digest(/:size)"
|
41
|
+
```
|
56
42
|
|
57
|
-
##
|
43
|
+
## Rendering images in your views
|
58
44
|
|
59
|
-
|
60
|
-
|
61
|
-
of git, this should seem familiar.
|
45
|
+
You should use the provided helpers for displaying images, this will ensure
|
46
|
+
that the generated URLs are properly signed and timestamped.
|
62
47
|
|
63
|
-
|
64
|
-
|
65
|
-
line in your initializers:
|
48
|
+
To display the image at it's original size, use `dynamic_image_tag` without
|
49
|
+
any options.
|
66
50
|
|
67
|
-
|
51
|
+
```html
|
52
|
+
<%= dynamic_image_tag image %>
|
53
|
+
```
|
68
54
|
|
55
|
+
To resize it, specify a max size. This will scale the image down to fit, but
|
56
|
+
no cropping will occur.
|
69
57
|
|
70
|
-
|
58
|
+
```html
|
59
|
+
<%= dynamic_image_tag image, size: '400x400' %>
|
60
|
+
```
|
71
61
|
|
72
|
-
|
73
|
-
for the Pages CMS. It was later extracted as a Rails Engine for Rails
|
74
|
-
1.2 in 2007, which also marked the first public release as
|
75
|
-
dynamic_image_engine.
|
62
|
+
Setting `crop: true` will crop the image to the exact size.
|
76
63
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
system.
|
64
|
+
```html
|
65
|
+
<%= dynamic_image_tag image, size: '400x400', crop: true %>
|
66
|
+
```
|
81
67
|
|
82
|
-
|
83
|
-
2.3, and modified to work as a Rails 3 plugin. It's not directly
|
84
|
-
compatible with earlier versions, but upgrading shouldn't be more
|
85
|
-
trouble than migrating the files out of the database.
|
68
|
+
Omitting either dimension will render the image at an exact width or height.
|
86
69
|
|
70
|
+
```html
|
71
|
+
<%= dynamic_image_tag image, size: '400x' %>
|
72
|
+
```
|
87
73
|
|
88
|
-
|
74
|
+
`dynamic_image_path` and `dynamic_image_url` act pretty much like regular URL
|
75
|
+
helpers.
|
89
76
|
|
90
|
-
|
77
|
+
```html
|
78
|
+
<%= link_to "See image", dynamic_image_path(image) %>
|
79
|
+
```
|
91
80
|
|
92
|
-
|
93
|
-
a copy of this software and associated documentation files (the
|
94
|
-
"Software"), to deal in the Software without restriction, including
|
95
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
96
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
97
|
-
permit persons to whom the Software is furnished to do so, subject to
|
98
|
-
the following conditions:
|
81
|
+
## License
|
99
82
|
|
100
|
-
|
101
|
-
included in all copies or substantial portions of the Software.
|
83
|
+
Copyright 2006-2014 Inge Jørgensen
|
102
84
|
|
103
|
-
|
104
|
-
|
105
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
106
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
107
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
108
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
109
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
85
|
+
DynamicImage is released under the
|
86
|
+
[MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,33 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
3
|
|
4
|
-
|
4
|
+
APP_RAKEFILE = "spec/internal/Rakefile"
|
5
|
+
load 'rails/tasks/engine.rake'
|
5
6
|
|
6
|
-
|
7
|
-
require "jeweler"
|
8
|
-
Jeweler::Tasks.new do |gem|
|
9
|
-
gem.name = "dynamic_image"
|
10
|
-
gem.summary = "DynamicImage is a rails plugin providing transparent uploading and processing of image files."
|
11
|
-
gem.email = "inge@elektronaut.no"
|
12
|
-
gem.homepage = "http://github.com/elektronaut/dynamic_image"
|
13
|
-
gem.authors = ["Inge Jørgensen"]
|
14
|
-
gem.files = Dir["*", "{lib}/**/*", "{app}/**/*", "{config}/**/*"]
|
15
|
-
gem.add_dependency("rmagick", "~> 2.13.2")
|
16
|
-
gem.add_dependency("vector2d", "~> 1.0.0")
|
17
|
-
end
|
18
|
-
Jeweler::GemcutterTasks.new
|
19
|
-
rescue LoadError
|
20
|
-
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
-
end
|
22
|
-
|
23
|
-
desc 'Default: run unit tests.'
|
24
|
-
task :default => :test
|
25
|
-
|
26
|
-
desc 'Test the dynamic_image plugin.'
|
27
|
-
Rake::TestTask.new(:test) do |t|
|
28
|
-
t.libs << 'lib'
|
29
|
-
t.libs << 'test'
|
30
|
-
t.pattern = 'test/**/*_test.rb'
|
31
|
-
t.verbose = true
|
32
|
-
end
|
7
|
+
RSpec::Core::RakeTask.new
|
33
8
|
|
9
|
+
task :default => :spec
|
10
|
+
task :test => :spec
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module DynamicImage
|
4
|
+
# = DynamicImage Belongs To
|
5
|
+
#
|
6
|
+
module BelongsTo
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def belongs_to_image(name, scope=nil, options={})
|
11
|
+
belongs_to(name, scope, options)
|
12
|
+
|
13
|
+
define_method "#{name}=" do |new_image|
|
14
|
+
if new_image.present? && !new_image.kind_of?(DynamicImage::Model)
|
15
|
+
new_image = self.send("build_#{name}", file: new_image)
|
16
|
+
end
|
17
|
+
super(new_image)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module DynamicImage
|
4
|
+
# = DynamicImage Controller
|
5
|
+
#
|
6
|
+
# Generating images is rather expensive, so all requests must be
|
7
|
+
# signed with a HMAC digest in order to avoid denial of service attacks.
|
8
|
+
# The methods in +DynamicImage::Helper+ handles this transparently.
|
9
|
+
# As a bonus, this also prevents unauthorized URL enumeration.
|
10
|
+
module Controller
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
before_action :verify_signed_params
|
15
|
+
before_action :find_record
|
16
|
+
after_action :cache_expiration_header
|
17
|
+
respond_to :gif, :jpeg, :png, :tiff
|
18
|
+
end
|
19
|
+
|
20
|
+
# Renders the image.
|
21
|
+
def show
|
22
|
+
render_image(format: requested_format)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Same as +show+, but renders the image without any pre-cropping applied.
|
26
|
+
def uncropped
|
27
|
+
render_image(format: requested_format, uncropped: true)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Renders the original image data, without any processing.
|
31
|
+
def original
|
32
|
+
if stale?(@record)
|
33
|
+
respond_with(@record) do |format|
|
34
|
+
format.any(:gif, :jpeg, :png, :tiff) do
|
35
|
+
send_data(
|
36
|
+
@record.data,
|
37
|
+
content_type: @record.content_type,
|
38
|
+
disposition: 'inline'
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def cache_expiration_header
|
48
|
+
expires_in 30.days, public: true
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_record
|
52
|
+
@record = model.find(params[:id])
|
53
|
+
end
|
54
|
+
|
55
|
+
def render_image(options)
|
56
|
+
processed_image = DynamicImage::ProcessedImage.new(@record, options)
|
57
|
+
if stale?(@record)
|
58
|
+
respond_with(@record) do |format|
|
59
|
+
format.any(:gif, :jpeg, :png, :tiff) do
|
60
|
+
send_data(
|
61
|
+
processed_image.cropped_and_resized(requested_size),
|
62
|
+
content_type: processed_image.content_type,
|
63
|
+
disposition: 'inline'
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def requested_format
|
71
|
+
params[:format]
|
72
|
+
end
|
73
|
+
|
74
|
+
def requested_size
|
75
|
+
Vector2d.parse(params[:size])
|
76
|
+
end
|
77
|
+
|
78
|
+
def signed_params
|
79
|
+
case request[:action]
|
80
|
+
when "show", "uncropped"
|
81
|
+
[:action, :id, :size]
|
82
|
+
else
|
83
|
+
[:action, :id]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def verify_signed_params
|
88
|
+
key = signed_params.map { |k|
|
89
|
+
k == :id ? params.require(k).to_i : params.require(k)
|
90
|
+
}.join('-')
|
91
|
+
DynamicImage.digest_verifier.verify(key, params[:digest])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module DynamicImage
|
4
|
+
# = DynamicImage Digest Verifier
|
5
|
+
#
|
6
|
+
# ==== Usage
|
7
|
+
#
|
8
|
+
# verifier = DynamicImage::DigestVerifier.new("super secret!")
|
9
|
+
#
|
10
|
+
# digest = verifier.generate("foo")
|
11
|
+
#
|
12
|
+
# digest.verify("foo", digest)
|
13
|
+
# # => true
|
14
|
+
# digest.verify("bar", digest)
|
15
|
+
# # => raises DynamicImage::Errors::InvalidSignature
|
16
|
+
#
|
17
|
+
# Credit where credit is due: adapted and simplified from
|
18
|
+
# +ActiveSupport::MessageVerifier+, since we don't need to handle
|
19
|
+
# arbitrary data structures and ship the serialized data to the client.
|
20
|
+
class DigestVerifier
|
21
|
+
def initialize(secret, options = {})
|
22
|
+
@secret = secret
|
23
|
+
@digest = options[:digest] || 'SHA1'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Generates a digest for a string.
|
27
|
+
def generate(data)
|
28
|
+
generate_digest(data)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Verifies that <tt>digest</tt> is valid for <tt>data</tt>.
|
32
|
+
# Raises a +DynamicImage::Errors::InvalidSignature+ error if not.
|
33
|
+
def verify(data, digest)
|
34
|
+
if valid_digest?(data, digest)
|
35
|
+
true
|
36
|
+
else
|
37
|
+
raise DynamicImage::Errors::InvalidSignature
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def secure_compare(a, b)
|
44
|
+
return false unless a.bytesize == b.bytesize
|
45
|
+
|
46
|
+
l = a.unpack "C#{a.bytesize}"
|
47
|
+
|
48
|
+
res = 0
|
49
|
+
b.each_byte { |byte| res |= byte ^ l.shift }
|
50
|
+
res == 0
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_digest(data)
|
54
|
+
require 'openssl' unless defined?(OpenSSL)
|
55
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data)
|
56
|
+
end
|
57
|
+
|
58
|
+
def valid_digest?(data, digest)
|
59
|
+
data.present? && digest.present? && secure_compare(digest, generate_digest(data))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module DynamicImage
|
4
|
+
module Errors
|
5
|
+
class Error < StandardError; end
|
6
|
+
class InvalidImage < DynamicImage::Errors::Error; end
|
7
|
+
class InvalidSignature < DynamicImage::Errors::Error; end
|
8
|
+
class InvalidSizeOptions < DynamicImage::Errors::Error; end
|
9
|
+
end
|
10
|
+
end
|
data/lib/dynamic_image/helper.rb
CHANGED
@@ -1,107 +1,161 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
3
|
module DynamicImage
|
4
|
+
# = DynamicImage Helper
|
5
|
+
#
|
6
|
+
# Provides helper methods for rendering and linking to images.
|
4
7
|
module Helper
|
8
|
+
# Returns the path for a DynamicImage::Model record.
|
9
|
+
# Takes the same options as +dynamic_image_url+
|
10
|
+
def dynamic_image_path(record_or_array, options={})
|
11
|
+
dynamic_image_url(record_or_array, { routing_type: :path }.merge(options))
|
12
|
+
end
|
5
13
|
|
6
|
-
# Returns an
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
# Returns an HTML image tag for the record. If no size is given, it will
|
15
|
+
# render at the original size.
|
16
|
+
#
|
17
|
+
# ==== Options
|
18
|
+
# * <tt>:alt</tt>: If no alt text is given, it will default to the
|
19
|
+
# filename of the uploaded image.
|
20
|
+
#
|
21
|
+
# See +dynamic_image_url+ for info on how to size and cropping. Options
|
22
|
+
# supported by +polymorphic_url+ will be passed to the router. Any other
|
23
|
+
# options will be added as HTML attributes.
|
24
|
+
#
|
25
|
+
# ==== Examples
|
26
|
+
#
|
27
|
+
# image = Image.find(params[:id])
|
28
|
+
# dynamic_image_tag(image)
|
29
|
+
# # => <img alt="My file" height="200" src="..." width="320" />
|
30
|
+
# dynamic_image_tag(image, size: "100x100", alt="Avatar")
|
31
|
+
# # => <img alt="Avatar" height="62" src="..." width="100" />
|
32
|
+
def dynamic_image_tag(record_or_array, options={})
|
33
|
+
record = extract_record(record_or_array)
|
34
|
+
options = {
|
35
|
+
alt: image_alt(record.filename)
|
36
|
+
}.merge(options)
|
37
|
+
|
38
|
+
size = fit_size!(record_or_array, options)
|
39
|
+
url_options = options.extract!(*allowed_dynamic_image_url_options)
|
40
|
+
html_options = { size: size }.merge(options)
|
41
|
+
|
42
|
+
image_tag(
|
43
|
+
dynamic_image_path_with_size(
|
44
|
+
record_or_array,
|
45
|
+
size,
|
46
|
+
url_options
|
47
|
+
),
|
48
|
+
html_options
|
49
|
+
)
|
50
|
+
end
|
13
51
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
52
|
+
# Returns the URL for a DynamicImage::Model record.
|
53
|
+
#
|
54
|
+
# ==== Options
|
55
|
+
#
|
56
|
+
# * <tt>:size</tt> - Desired image size, supplied as "{width}x{height}".
|
57
|
+
# The image will be scaled to fit. A partial size like "100x" or "x100"
|
58
|
+
# can be given, if you want a fixed width or height.
|
59
|
+
# * <tt>:crop</tt> - If true, the image will be cropped to the given size.
|
60
|
+
# * <tt>:upscale</tt> - By default, DynamicImage only scale images down,
|
61
|
+
# never up. Pass <tt>upscale: true</tt> to force upscaling.
|
62
|
+
#
|
63
|
+
# Any options supported by +polymorphic_url+ are also accepted.
|
64
|
+
#
|
65
|
+
# ==== Examples
|
66
|
+
#
|
67
|
+
# image = Image.find(params[:id])
|
68
|
+
# dynamic_image_url(image)
|
69
|
+
# # => "http://example.com/images/96...d1/300x187/1-2014062020...00.jpg"
|
70
|
+
# dynamic_image_url(image, size: '100x100')
|
71
|
+
# # => "http://example.com/images/72...c2/100x62/1-2014062020...00.jpg"
|
72
|
+
# dynamic_image_url(image, size: '100x100', crop: true)
|
73
|
+
# # => "http://example.com/images/a4...6b/100x100/1-2014062020...00.jpg"
|
74
|
+
def dynamic_image_url(record_or_array, options={})
|
75
|
+
size = fit_size!(record_or_array, options)
|
76
|
+
dynamic_image_url_with_size(record_or_array, size, options)
|
77
|
+
end
|
18
78
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
79
|
+
# Returns a path to the original uploaded file, without any processing
|
80
|
+
# applied. Sizing options are not supported.
|
81
|
+
def original_dynamic_image_path(record_or_array, options={})
|
82
|
+
dynamic_image_path(record_or_array, { action: :original }.merge(options))
|
83
|
+
end
|
23
84
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
85
|
+
# Returns a URL to the original uploaded file, without any processing
|
86
|
+
# applied. Sizing options are not supported.
|
87
|
+
def original_dynamic_image_url(record_or_array, options={})
|
88
|
+
dynamic_image_url(record_or_array, { action: :original }.merge(options))
|
89
|
+
end
|
28
90
|
|
29
|
-
|
30
|
-
|
31
|
-
|
91
|
+
# Same as +dynamic_image_path+, but points to an image with any
|
92
|
+
# pre-cropping disabled.
|
93
|
+
def uncropped_dynamic_image_path(record_or_array, options={})
|
94
|
+
dynamic_image_path(record_or_array, { action: :uncropped }.merge(options))
|
95
|
+
end
|
32
96
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
97
|
+
# Same as +dynamic_image_tag+, but renders an image with any
|
98
|
+
# pre-cropping disabled.
|
99
|
+
def uncropped_dynamic_image_tag(record_or_array, options={})
|
100
|
+
dynamic_image_tag(record_or_array, { action: :uncropped }.merge(options))
|
101
|
+
end
|
37
102
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
103
|
+
# Same as +dynamic_image_url+, but points to an image with any
|
104
|
+
# pre-cropping disabled.
|
105
|
+
def uncropped_dynamic_image_url(record_or_array, options={})
|
106
|
+
dynamic_image_url(record_or_array, { action: :uncropped }.merge(options))
|
107
|
+
end
|
42
108
|
|
43
|
-
|
44
|
-
if options[:filterset]
|
45
|
-
url_options[:filterset] = options[:filterset]
|
46
|
-
options.delete :filterset
|
47
|
-
end
|
109
|
+
private
|
48
110
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
else
|
57
|
-
url_options[:filename] = image.filename
|
58
|
-
end
|
111
|
+
def allowed_dynamic_image_url_options
|
112
|
+
[
|
113
|
+
:format, :only_path, :protocol, :host, :subdomain, :domain,
|
114
|
+
:tld_length, :port, :anchor, :trailing_slash, :script_name,
|
115
|
+
:action, :routing_type
|
116
|
+
]
|
117
|
+
end
|
59
118
|
|
60
|
-
|
61
|
-
|
62
|
-
|
119
|
+
def default_format_for_image(record)
|
120
|
+
Mime::Type.lookup(record.safe_content_type).to_sym
|
121
|
+
end
|
63
122
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
if options.has_key?(:host)
|
69
|
-
url_options[:host] = options[:host]
|
70
|
-
options[:host] = nil
|
71
|
-
end
|
123
|
+
def dynamic_image_digest(record, action, size=nil)
|
124
|
+
key = [action || 'show', record.id, size].compact.join('-')
|
125
|
+
DynamicImage.digest_verifier.generate(key)
|
126
|
+
end
|
72
127
|
|
73
|
-
|
128
|
+
def dynamic_image_path_with_size(record_or_array, size=nil, options={})
|
129
|
+
dynamic_image_url_with_size(record_or_array, size, { routing_type: :path }.merge(options))
|
74
130
|
end
|
75
131
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
# ==== Examples
|
87
|
-
#
|
88
|
-
# dynamic_image_tag(@image) # Original image
|
89
|
-
# dynamic_image_tag(@image, :size => "100x") # Will be 100px wide
|
90
|
-
# dynamic_image_tag(@image, :size => "100x100") # Will fit within 100x100
|
91
|
-
# dynamic_image_tag(@image, :size => "100x100", :crop => true) # Will be cropped to 100x100
|
92
|
-
#
|
93
|
-
def dynamic_image_tag(image, options = {})
|
94
|
-
parsed_options = dynamic_image_options(image, options)
|
95
|
-
image_tag(parsed_options[:url], parsed_options[:options] ).gsub(/\?[\d]+/,'').html_safe
|
132
|
+
def dynamic_image_url_with_size(record_or_array, size=nil, options={})
|
133
|
+
record = extract_record(record_or_array)
|
134
|
+
options = {
|
135
|
+
routing_type: :url,
|
136
|
+
action: nil,
|
137
|
+
format: default_format_for_image(record),
|
138
|
+
size: size
|
139
|
+
}.merge(options)
|
140
|
+
options[:digest] = dynamic_image_digest(record, options[:action], options[:size])
|
141
|
+
polymorphic_url(record_or_array, options)
|
96
142
|
end
|
97
143
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
144
|
+
def fit_size!(record_or_array, options)
|
145
|
+
record = extract_record(record_or_array)
|
146
|
+
action = options[:action].try(:to_s)
|
147
|
+
size_opts = options.extract!(:size, :crop, :upscale)
|
148
|
+
|
149
|
+
if size_opts[:size]
|
150
|
+
DynamicImage::ImageSizing.new(
|
151
|
+
record,
|
152
|
+
uncropped: (action == "uncropped")
|
153
|
+
).fit(size_opts[:size], size_opts).floor.to_s
|
154
|
+
elsif action != "original"
|
155
|
+
record.size.floor.to_s
|
156
|
+
else
|
157
|
+
nil
|
158
|
+
end
|
103
159
|
end
|
104
160
|
end
|
105
161
|
end
|
106
|
-
|
107
|
-
ActionView::Base.send(:include, DynamicImage::Helper)
|