dynamic_image 1.0.0 → 1.0.1
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.
- data/LICENSE +20 -0
- data/README.md +102 -12
- data/Rakefile +33 -0
- data/VERSION +1 -0
- data/app/controllers/images_controller.rb +79 -0
- data/app/models/image.rb +188 -0
- data/config/routes.rb +16 -0
- data/dynamic_image.gemspec +22 -1
- data/dynamic_image.sublime-project +9 -0
- data/dynamic_image.sublime-workspace +1599 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/binary_storage/active_record_extensions.rb +144 -0
- data/lib/binary_storage/blob.rb +104 -0
- data/lib/binary_storage.rb +28 -0
- data/lib/dynamic_image/active_record_extensions.rb +60 -0
- data/lib/dynamic_image/engine.rb +6 -0
- data/lib/dynamic_image/filterset.rb +79 -0
- data/lib/dynamic_image/helper.rb +107 -0
- data/lib/dynamic_image.rb +78 -0
- data/lib/generators/dynamic_image/USAGE +5 -0
- data/lib/generators/dynamic_image/dynamic_image_generator.rb +38 -0
- data/lib/generators/dynamic_image/templates/migrations/create_images.rb +21 -0
- data/uninstall.rb +1 -0
- metadata +27 -4
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006-2010 Inge Jørgensen
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,19 +1,109 @@
|
|
1
1
|
# DynamicImage
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
> (...)
|
7
|
-
> When you throw away code and start from scratch, you are throwing away all
|
8
|
-
> that knowledge. All those collected bug fixes. Years of programming work.
|
9
|
-
> _-Joel Spolsky_
|
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.
|
10
6
|
|
11
|
-
|
7
|
+
Note: This version is currently Rails 3 specific, although the final 1.0
|
8
|
+
version will also be compatible with 2.x.
|
12
9
|
|
13
|
-
DynamicImage is being rewritten.
|
14
10
|
|
15
|
-
##
|
11
|
+
## Installation
|
16
12
|
|
17
|
-
|
13
|
+
Install the gem:
|
18
14
|
|
19
|
-
|
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
|
28
|
+
|
29
|
+
Let's create a model with an image:
|
30
|
+
|
31
|
+
class User
|
32
|
+
belongs_to_image :mugshot
|
33
|
+
end
|
34
|
+
|
35
|
+
Uploading files is pretty straightforward, just add a <tt>file_field</tt>
|
36
|
+
to your form and update your record as usual:
|
37
|
+
|
38
|
+
<%= form_for @user, :html => {:multipart => true} do |f| %>
|
39
|
+
Name: <%= f.text_field :name %>
|
40
|
+
Mugshot: <%= f.file_field :mugshot %>
|
41
|
+
<%= submit_tag "Save" %>
|
42
|
+
<% end %>
|
43
|
+
|
44
|
+
You can now use the <tt>dynamic_image_tag</tt> helper to show off your
|
45
|
+
new image:
|
46
|
+
|
47
|
+
<% if @user.mugshot? %>
|
48
|
+
<%= dynamic_image_tag @user.profile_picture, :size => '64x64' %>
|
49
|
+
<% end %>
|
50
|
+
|
51
|
+
|
52
|
+
## Filters
|
53
|
+
|
54
|
+
I'm cleaning up the filters syntax, watch this space.
|
55
|
+
|
56
|
+
|
57
|
+
## Technical
|
58
|
+
|
59
|
+
The original master files are stored in the file system and identified a
|
60
|
+
SHA-1 hash of the contents. If you're familiar with the internal workings
|
61
|
+
of git, this should seem familiar.
|
62
|
+
|
63
|
+
Processing images on the fly is expensive. Therefore, page caching is enabled
|
64
|
+
by default, even in development mode. To disable page caching, add the following
|
65
|
+
line in your initializers:
|
66
|
+
|
67
|
+
DynamicImage.page_caching = false
|
68
|
+
|
69
|
+
|
70
|
+
## History
|
71
|
+
|
72
|
+
DynamicImage was originally created in early 2006 to handle images
|
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.
|
76
|
+
|
77
|
+
The API has remained more or less unchanged, but the internal workings
|
78
|
+
have been refactored a few times over the years, most notably dropping
|
79
|
+
the Engines dependency and transitioning from database storage to file
|
80
|
+
system.
|
81
|
+
|
82
|
+
The current version is based on an internal branch targeting Rails
|
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.
|
86
|
+
|
87
|
+
|
88
|
+
## Copyright
|
89
|
+
|
90
|
+
Copyright © 2006 Inge Jørgensen.
|
91
|
+
|
92
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
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:
|
99
|
+
|
100
|
+
The above copyright notice and this permission notice shall be
|
101
|
+
included in all copies or substantial portions of the Software.
|
102
|
+
|
103
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
104
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
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.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
require "rake"
|
5
|
+
|
6
|
+
begin
|
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
|
33
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.1
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class ImagesController < ActionController::Base
|
2
|
+
|
3
|
+
after_filter :cache_dynamic_image
|
4
|
+
after_filter :run_garbage_collection_for_dynamic_image_controller
|
5
|
+
|
6
|
+
unloadable
|
7
|
+
|
8
|
+
public
|
9
|
+
|
10
|
+
# Return the requested image. Rescale, filter and cache it where appropriate.
|
11
|
+
def render_dynamic_image
|
12
|
+
|
13
|
+
render_missing_image and return unless Image.exists?(params[:id])
|
14
|
+
image = Image.find(params[:id])
|
15
|
+
|
16
|
+
minTime = Time.rfc2822(request.env["HTTP_IF_MODIFIED_SINCE"]) rescue nil
|
17
|
+
if minTime && image.created_at? && image.created_at <= minTime
|
18
|
+
render :text => '304 Not Modified', :status => 304
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
unless image.data?
|
23
|
+
logger.warn "Image #{image.id} exists, but has no data"
|
24
|
+
render_missing_image and return
|
25
|
+
end
|
26
|
+
|
27
|
+
if size = params[:size]
|
28
|
+
if size =~ /^x[\d]+$/ || size =~ /^[\d]+x$/
|
29
|
+
if params[:original]
|
30
|
+
image.cropped = false
|
31
|
+
end
|
32
|
+
size = Vector2d.new(size)
|
33
|
+
image_size = Vector2d.new(image.size)
|
34
|
+
size = image_size.constrain_both(size).round.to_s
|
35
|
+
end
|
36
|
+
imagedata = image.get_processed(size, params[:filterset])
|
37
|
+
else
|
38
|
+
imagedata = image
|
39
|
+
end
|
40
|
+
|
41
|
+
DynamicImage.dirty_memory = true # Flag memory for GC
|
42
|
+
|
43
|
+
if image
|
44
|
+
response.headers['Cache-Control'] = nil
|
45
|
+
response.headers['Last-Modified'] = imagedata.created_at.httpdate if imagedata.created_at?
|
46
|
+
send_data(
|
47
|
+
imagedata.data,
|
48
|
+
:filename => image.filename,
|
49
|
+
:type => image.content_type,
|
50
|
+
:disposition => 'inline'
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def render_missing_image
|
59
|
+
if self.respond_to?(:render_error)
|
60
|
+
render_error 404
|
61
|
+
else
|
62
|
+
render :status => 404, :text => "404: Image not found"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Enforce caching of dynamic images, even if caching is turned off
|
67
|
+
def cache_dynamic_image
|
68
|
+
cache_setting = ActionController::Base.perform_caching
|
69
|
+
ActionController::Base.perform_caching = true
|
70
|
+
cache_page
|
71
|
+
ActionController::Base.perform_caching = cache_setting
|
72
|
+
end
|
73
|
+
|
74
|
+
# Perform garbage collection if necessary
|
75
|
+
def run_garbage_collection_for_dynamic_image_controller
|
76
|
+
DynamicImage.clean_dirty_memory
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/app/models/image.rb
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
class Image < ActiveRecord::Base
|
2
|
+
unloadable
|
3
|
+
|
4
|
+
binary_storage :data, :sha1_hash
|
5
|
+
|
6
|
+
validates_format_of :content_type,
|
7
|
+
:with => /^image/,
|
8
|
+
:message => "you can only upload pictures"
|
9
|
+
|
10
|
+
attr_accessor :filterset, :data_checked, :skip_maxsize
|
11
|
+
|
12
|
+
# Sanitize the filename and set the name to the filename if omitted
|
13
|
+
validate do |image|
|
14
|
+
image.name = File.basename(image.filename, ".*") if !image.name || image.name.strip == ""
|
15
|
+
image.filename = image.friendly_file_name(image.filename)
|
16
|
+
if image.cropped?
|
17
|
+
image.errors.add(:crop_start, "must be a vector") unless image.crop_start =~ /^[\d]+x[\d]+$/
|
18
|
+
image.errors.add(:crop_size, "must be a vector") unless image.crop_size =~ /^[\d]+x[\d]+$/
|
19
|
+
else
|
20
|
+
image.crop_size = image.original_size
|
21
|
+
image.crop_start = "0x0"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create the binary from an image file.
|
26
|
+
def imagefile=(image_file)
|
27
|
+
if image_file.kind_of?(String) && image_file =~ /^(ht|f)tps?:\/\//
|
28
|
+
self.filename = File.basename(image_file)
|
29
|
+
image_file = open(image_file)
|
30
|
+
else
|
31
|
+
self.filename = image_file.original_filename rescue File.basename(image_file.path)
|
32
|
+
end
|
33
|
+
self.content_type = image_file.content_type.chomp rescue "image/"+image_file.path.split(/\./).last.downcase.gsub(/jpg/,"jpeg") # ugly hack
|
34
|
+
set_image_data(image_file.read)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return the image hotspot
|
38
|
+
def hotspot
|
39
|
+
(self.hotspot?) ? self.hotspot : (Vector2d.new(self.size) * 0.5).round.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
# Check the image data
|
43
|
+
def set_image_data(data)
|
44
|
+
self.data = data
|
45
|
+
if self.data
|
46
|
+
image = Magick::ImageList.new.from_blob(self.data)
|
47
|
+
size = Vector2d.new(image.columns, image.rows)
|
48
|
+
if DynamicImage.crash_size
|
49
|
+
crashsize = Vector2d.new(DynamicImage.crash_size)
|
50
|
+
if (size.x > crashsize.x || size.y > crashsize.y)
|
51
|
+
raise "Image too large!"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if DynamicImage.max_size && !self.skip_maxsize
|
55
|
+
maxsize = Vector2d.new(DynamicImage.max_size)
|
56
|
+
if (size.x > maxsize.x || size.y > maxsize.y)
|
57
|
+
size = size.constrain_both(maxsize).round
|
58
|
+
image.resize!(size.x, size.y)
|
59
|
+
self.data = image.to_blob
|
60
|
+
end
|
61
|
+
end
|
62
|
+
# Convert image to a proper format
|
63
|
+
unless image.format =~ /(JPEG|PNG|GIF)/
|
64
|
+
self.data = image.to_blob{self.format = 'JPEG'; self.quality = 90}
|
65
|
+
self.filename += ".jpg"
|
66
|
+
self.content_type = "image/jpeg"
|
67
|
+
end
|
68
|
+
self.original_size = size.round.to_s
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the image width
|
73
|
+
def original_width
|
74
|
+
Vector2d.new(self.original_size).x.to_i
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the image height
|
78
|
+
def original_height
|
79
|
+
Vector2d.new(self.original_size).y.to_i
|
80
|
+
end
|
81
|
+
|
82
|
+
def crop_start_x
|
83
|
+
Vector2d.new(self.crop_start).x.to_i
|
84
|
+
end
|
85
|
+
def crop_start_y
|
86
|
+
Vector2d.new(self.crop_start).y.to_i
|
87
|
+
end
|
88
|
+
def crop_width
|
89
|
+
Vector2d.new(self.crop_size).x.to_i
|
90
|
+
end
|
91
|
+
def crop_height
|
92
|
+
Vector2d.new(self.crop_size).y.to_i
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns original or cropped size
|
96
|
+
def size
|
97
|
+
(self.cropped?) ? self.crop_size : self.original_size
|
98
|
+
end
|
99
|
+
|
100
|
+
def size=(new_size)
|
101
|
+
self.original_size = new_size
|
102
|
+
end
|
103
|
+
|
104
|
+
# Convert file name to a more file system friendly one.
|
105
|
+
# TODO: international chars
|
106
|
+
def friendly_file_name( file_name )
|
107
|
+
[["æ","ae"], ["ø","oe"], ["å","aa"]].each do |int|
|
108
|
+
file_name = file_name.gsub(int[0], int[1])
|
109
|
+
end
|
110
|
+
File.basename(file_name).gsub(/[^\w\d\.-]/, "_")
|
111
|
+
end
|
112
|
+
|
113
|
+
# Get the base part of a filename
|
114
|
+
def base_part_of(file_name)
|
115
|
+
name = File.basename(file_name)
|
116
|
+
name.gsub(/[ˆ\w._-]/, '')
|
117
|
+
end
|
118
|
+
|
119
|
+
# Rescale and crop the image, and return it as a blob.
|
120
|
+
def rescaled_and_cropped_data(*args)
|
121
|
+
DynamicImage.dirty_memory = true # Flag to perform GC
|
122
|
+
image_data = Magick::ImageList.new.from_blob(self.data)
|
123
|
+
|
124
|
+
if self.cropped?
|
125
|
+
cropped_start = Vector2d.new(self.crop_start).round
|
126
|
+
cropped_size = Vector2d.new(self.crop_size).round
|
127
|
+
image_data = image_data.crop(cropped_start.x, cropped_start.y, cropped_size.x, cropped_size.y, true)
|
128
|
+
end
|
129
|
+
|
130
|
+
size = Vector2d.new(self.size)
|
131
|
+
rescale_size = size.dup.constrain_one(args).round # Rescale dimensions
|
132
|
+
crop_to_size = Vector2d.new(args).round # Crop size
|
133
|
+
new_hotspot = Vector2d.new(hotspot) * (rescale_size / size) # Recalculated hotspot
|
134
|
+
rect = [(new_hotspot-(crop_to_size/2)).round, (new_hotspot+(crop_to_size/2)).round] # Array containing crop coords
|
135
|
+
|
136
|
+
# Adjustments
|
137
|
+
x = rect[0].x; rect.each{|r| r.x += (x.abs)} if x < 0
|
138
|
+
y = rect[0].y; rect.each{|r| r.y += (y.abs)} if y < 0
|
139
|
+
x = rect[1].x; rect.each{|r| r.x -= (x-rescale_size.x)} if x > rescale_size.x
|
140
|
+
y = rect[1].y; rect.each{|r| r.y -= (y-rescale_size.y)} if y > rescale_size.y
|
141
|
+
|
142
|
+
rect[0].round!
|
143
|
+
rect[1].round!
|
144
|
+
|
145
|
+
image_data = image_data.resize(rescale_size.x, rescale_size.y)
|
146
|
+
image_data = image_data.crop(rect[0].x, rect[0].y, crop_to_size.x, crop_to_size.y)
|
147
|
+
image_data.to_blob{self.quality = 90}
|
148
|
+
end
|
149
|
+
|
150
|
+
def constrain_size(*max_size)
|
151
|
+
Vector2d.new(self.size).constrain_both(max_size.flatten).round.to_s
|
152
|
+
end
|
153
|
+
|
154
|
+
# Get a duplicate image with resizing and filters applied.
|
155
|
+
def get_processed(size, filterset=nil)
|
156
|
+
size = Vector2d.new(size).round.to_s
|
157
|
+
processed_image = Image.new
|
158
|
+
processed_image.filterset = filterset || 'default'
|
159
|
+
processed_image.data = self.rescaled_and_cropped_data(size)
|
160
|
+
processed_image.size = size
|
161
|
+
processed_image.apply_filters
|
162
|
+
processed_image
|
163
|
+
end
|
164
|
+
|
165
|
+
# Apply filters to image data
|
166
|
+
def apply_filters
|
167
|
+
filterset_name = self.filterset || 'default'
|
168
|
+
filterset = DynamicImage::Filterset[filterset_name]
|
169
|
+
if filterset
|
170
|
+
DynamicImage.dirty_memory = true # Flag for GC
|
171
|
+
data = Magick::ImageList.new.from_blob(self.data)
|
172
|
+
data = filterset.process(data)
|
173
|
+
self.data = data.to_blob
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Decorates to_json with additional attributes
|
178
|
+
def to_json
|
179
|
+
attributes.merge({
|
180
|
+
:original_width => self.original_width,
|
181
|
+
:original_height => self.original_height,
|
182
|
+
:crop_width => self.crop_width,
|
183
|
+
:crop_height => self.crop_height,
|
184
|
+
:crop_start_x => self.crop_start_x,
|
185
|
+
:crop_start_y => self.crop_start_y
|
186
|
+
}).to_json
|
187
|
+
end
|
188
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Rails 3 routes
|
2
|
+
Rails.application.routes.draw do
|
3
|
+
match "dynamic_images/:id/:original(/:size(/:filterset))/*filename" => "images#render_dynamic_image", :size => /\d*x\d*/, :original => /original/
|
4
|
+
match "dynamic_images/:id(/:size(/:filterset))/*filename" => "images#render_dynamic_image", :size => /\d*x\d*/
|
5
|
+
# Legacy
|
6
|
+
match "dynamic_image/:id/:original(/:size(/:filterset))/*filename" => "images#render_dynamic_image", :size => /\d*x\d*/, :original => /original/
|
7
|
+
match "dynamic_image/:id(/:size(/:filterset))/*filename" => "images#render_dynamic_image", :size => /\d*x\d*/
|
8
|
+
end
|
9
|
+
|
10
|
+
# Rails 2 routes
|
11
|
+
#@set.add_route('dynamic_image/:id/:original/:size/:filterset/*filename', {:controller => 'images', :action => 'render_dynamic_image', :requirements => { :size => /[\d]*x[\d]*/, :original => /original/ }})
|
12
|
+
#@set.add_route('dynamic_image/:id/:original/:size/*filename', {:controller => 'images', :action => 'render_dynamic_image', :requirements => { :size => /[\d]*x[\d]*/, :original => /original/ }})
|
13
|
+
#@set.add_route('dynamic_image/:id/:original/*filename', {:controller => 'images', :action => 'render_dynamic_image', :requirements => { :original => /original/ }})
|
14
|
+
#@set.add_route('dynamic_image/:id/:size/:filterset/*filename', {:controller => 'images', :action => 'render_dynamic_image', :requirements => { :size => /[\d]*x[\d]*/ }})
|
15
|
+
#@set.add_route('dynamic_image/:id/:size/*filename', {:controller => 'images', :action => 'render_dynamic_image', :requirements => { :size => /[\d]*x[\d]*/ }})
|
16
|
+
#@set.add_route('dynamic_image/:id/*filename', {:controller => 'images', :action => 'render_dynamic_image'})
|
data/dynamic_image.gemspec
CHANGED
@@ -12,11 +12,32 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.date = "2014-06-12"
|
13
13
|
s.email = "inge@elektronaut.no"
|
14
14
|
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
15
16
|
"README.md"
|
16
17
|
]
|
17
18
|
s.files = [
|
19
|
+
"LICENSE",
|
18
20
|
"README.md",
|
19
|
-
"
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"app/controllers/images_controller.rb",
|
24
|
+
"app/models/image.rb",
|
25
|
+
"config/routes.rb",
|
26
|
+
"dynamic_image.gemspec",
|
27
|
+
"init.rb",
|
28
|
+
"install.rb",
|
29
|
+
"lib/binary_storage.rb",
|
30
|
+
"lib/binary_storage/active_record_extensions.rb",
|
31
|
+
"lib/binary_storage/blob.rb",
|
32
|
+
"lib/dynamic_image.rb",
|
33
|
+
"lib/dynamic_image/active_record_extensions.rb",
|
34
|
+
"lib/dynamic_image/engine.rb",
|
35
|
+
"lib/dynamic_image/filterset.rb",
|
36
|
+
"lib/dynamic_image/helper.rb",
|
37
|
+
"lib/generators/dynamic_image/USAGE",
|
38
|
+
"lib/generators/dynamic_image/dynamic_image_generator.rb",
|
39
|
+
"lib/generators/dynamic_image/templates/migrations/create_images.rb",
|
40
|
+
"uninstall.rb"
|
20
41
|
]
|
21
42
|
s.homepage = "http://github.com/elektronaut/dynamic_image"
|
22
43
|
s.require_paths = ["lib"]
|