dynamic_image 1.0.4 → 2.0.0.beta1
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.
- 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 [](https://travis-ci.org/elektronaut/dynamic_image) [](https://codeclimate.com/github/elektronaut/dynamic_image) [](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)
|