dynamic_image 0.9.5 → 0.9.6

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/lib/dynamic_image.rb CHANGED
@@ -13,8 +13,8 @@ require 'active_record'
13
13
  require 'binary_storage'
14
14
 
15
15
  if Rails::VERSION::MAJOR == 3
16
- # Load the engine
17
- require 'dynamic_image/engine' if defined?(Rails)
16
+ # Load the engine
17
+ require 'dynamic_image/engine' if defined?(Rails)
18
18
  end
19
19
 
20
20
  require 'dynamic_image/active_record_extensions'
@@ -22,57 +22,57 @@ require 'dynamic_image/filterset'
22
22
  require 'dynamic_image/helper'
23
23
 
24
24
  module DynamicImage
25
- @@dirty_memory = false
26
- @@page_caching = true
27
-
28
- class << self
29
-
30
- def dirty_memory=(flag)
31
- @@dirty_memory = flag
32
- end
33
-
34
- def dirty_memory
35
- @@dirty_memory
36
- end
37
-
38
- def page_caching=(flag)
39
- @@page_caching = flag
40
- end
41
-
42
- def page_caching
43
- @@page_caching
44
- end
45
-
46
- def max_size
47
- @@max_size ||= "2000x2000"
48
- end
49
-
50
- def max_size=(new_max_size)
51
- @@max_size = new_max_size
52
- end
25
+ @@dirty_memory = false
26
+ @@page_caching = true
27
+
28
+ class << self
29
+
30
+ def dirty_memory=(flag)
31
+ @@dirty_memory = flag
32
+ end
33
+
34
+ def dirty_memory
35
+ @@dirty_memory
36
+ end
37
+
38
+ def page_caching=(flag)
39
+ @@page_caching = flag
40
+ end
41
+
42
+ def page_caching
43
+ @@page_caching
44
+ end
45
+
46
+ def max_size
47
+ @@max_size ||= "2000x2000"
48
+ end
49
+
50
+ def max_size=(new_max_size)
51
+ @@max_size = new_max_size
52
+ end
53
53
 
54
- def crash_size
55
- @@crash_size ||= "10000x10000"
56
- end
57
-
58
- def crash_size=(new_crash_size)
59
- @@crash_size = new_crash_size
60
- end
54
+ def crash_size
55
+ @@crash_size ||= "10000x10000"
56
+ end
57
+
58
+ def crash_size=(new_crash_size)
59
+ @@crash_size = new_crash_size
60
+ end
61
61
 
62
- # RMagick stores image data internally, Ruby doesn't see the used memory.
63
- # This method performs garbage collection if @@dirty_memory has been flagged.
64
- # More details here: http://rubyforge.org/forum/message.php?msg_id=1995
65
- def clean_dirty_memory(options={})
66
- options.symbolize_keys!
67
- if @@dirty_memory || options[:force]
68
- gc_disabled = GC.enable
69
- GC.start
70
- GC.disable if gc_disabled
71
- @@dirty_memory = false
72
- true
73
- else
74
- false
75
- end
76
- end
77
- end
78
- end
62
+ # RMagick stores image data internally, Ruby doesn't see the used memory.
63
+ # This method performs garbage collection if @@dirty_memory has been flagged.
64
+ # More details here: http://rubyforge.org/forum/message.php?msg_id=1995
65
+ def clean_dirty_memory(options={})
66
+ options.symbolize_keys!
67
+ if @@dirty_memory || options[:force]
68
+ gc_disabled = GC.enable
69
+ GC.start
70
+ GC.disable if gc_disabled
71
+ @@dirty_memory = false
72
+ true
73
+ else
74
+ false
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,60 +1,60 @@
1
1
  require 'dynamic_image'
2
2
 
3
3
  module DynamicImage
4
- module ActiveRecordExtensions
4
+ module ActiveRecordExtensions
5
5
 
6
- def self.included(base)
7
- base.send :extend, ClassMethods
8
- end
6
+ def self.included(base)
7
+ base.send :extend, ClassMethods
8
+ end
9
9
 
10
- module ClassMethods
11
- # By using <tt>belongs_to_image</tt> over <tt>belongs_to</tt>, you gain the ability to
12
- # set the image directly from an uploaded file. This works exactly like <tt>belongs_to</tt>,
13
- # except the class name will default to 'Image' - not the name of the association.
14
- #
15
- # Example:
16
- #
17
- # # Model code
18
- # class Person < ActiveRecord::Base
19
- # belongs_to_image :mugshot
20
- # end
21
- #
22
- # # View code
23
- # <% form_for 'person', @person, :html => {:multipart => true} do |f| %>
24
- # <%= f.file_field :mugshot %>
25
- # <% end %>
26
- #
27
- def belongs_to_image(association_id, options={})
28
- options[:class_name] ||= 'Image'
29
- options[:foreign_key] ||= options[:class_name].downcase+'_id'
30
- belongs_to association_id, options
10
+ module ClassMethods
11
+ # By using <tt>belongs_to_image</tt> over <tt>belongs_to</tt>, you gain the ability to
12
+ # set the image directly from an uploaded file. This works exactly like <tt>belongs_to</tt>,
13
+ # except the class name will default to 'Image' - not the name of the association.
14
+ #
15
+ # Example:
16
+ #
17
+ # # Model code
18
+ # class Person < ActiveRecord::Base
19
+ # belongs_to_image :mugshot
20
+ # end
21
+ #
22
+ # # View code
23
+ # <% form_for 'person', @person, :html => {:multipart => true} do |f| %>
24
+ # <%= f.file_field :mugshot %>
25
+ # <% end %>
26
+ #
27
+ def belongs_to_image(association_id, options={})
28
+ options[:class_name] ||= 'Image'
29
+ options[:foreign_key] ||= options[:class_name].downcase+'_id'
30
+ belongs_to association_id, options
31
31
 
32
- # Overwrite the setter method
33
- class_eval <<-end_eval
34
- alias_method :associated_#{association_id}=, :#{association_id}=
35
- def #{association_id}=(img_obj)
36
- # Convert a Tempfile to a proper Image
37
- unless img_obj.kind_of?(ActiveRecord::Base)
38
- DynamicImage.dirty_memory = true # Flag for GC
39
- img_obj = Image.create(:imagefile => img_obj)
40
- end
41
- # Quietly skip blank strings
42
- unless img_obj.kind_of?(String) && img_obj.blank?
43
- self.associated_#{association_id} = img_obj
44
- end
45
- end
46
- def #{association_id}?
47
- (self.#{association_id} && self.#{association_id}.data?) ? true : false
48
- end
49
- end_eval
32
+ # Overwrite the setter method
33
+ class_eval <<-end_eval
34
+ alias_method :associated_#{association_id}=, :#{association_id}=
35
+ def #{association_id}=(img_obj)
36
+ # Convert a Tempfile to a proper Image
37
+ unless img_obj.kind_of?(ActiveRecord::Base)
38
+ DynamicImage.dirty_memory = true # Flag for GC
39
+ img_obj = Image.create(:imagefile => img_obj)
40
+ end
41
+ # Quietly skip blank strings
42
+ unless img_obj.kind_of?(String) && img_obj.blank?
43
+ self.associated_#{association_id} = img_obj
44
+ end
45
+ end
46
+ def #{association_id}?
47
+ (self.#{association_id} && self.#{association_id}.data?) ? true : false
48
+ end
49
+ end_eval
50
50
 
51
- send :include, DynamicImage::ActiveRecordExtensions::InstanceMethods
52
- end
53
- end
51
+ send :include, DynamicImage::ActiveRecordExtensions::InstanceMethods
52
+ end
53
+ end
54
54
 
55
- module InstanceMethods
56
- end
57
- end
55
+ module InstanceMethods
56
+ end
57
+ end
58
58
  end
59
59
 
60
60
  ActiveRecord::Base.send(:include, DynamicImage::ActiveRecordExtensions)
@@ -1,6 +1,6 @@
1
1
  require 'dynamic_image'
2
2
 
3
3
  module DynamicImage
4
- class Engine < Rails::Engine
5
- end
6
- end
4
+ class Engine < Rails::Engine
5
+ end
6
+ end
@@ -2,78 +2,78 @@ require 'dynamic_image'
2
2
 
3
3
  module DynamicImage
4
4
 
5
- @@filtersets = Hash.new
6
-
7
- # Singleton methods for the filtersets hash.
8
- class << @@filtersets
9
- def names; keys; end
10
- end
11
-
12
- # Accessor for the filtersets hash. Installed filter names are available through the <tt>names</tt> method. Example:
13
- # @filter_names = DynamicImage.filtersets.names
14
- def self.filtersets
15
- @@filtersets
16
- end
17
-
18
- # Base class for filter sets. Extending this with your own subclasses will automatically enable them for use.
19
- # You'll need to overwrite <tt>Filterset.process</tt> in order to make your filter useful. Note that it's a class
20
- # method.
21
- #
22
- # === Example
23
- #
24
- # class BlogThumbnailsFilterset < DynamicImage::Filterset
25
- # def self.process(image)
26
- # image = image.sepiatone # convert the image to sepia tones
27
- # end
28
- # end
29
- #
30
- # The filter set is now available for use in your application:
31
- #
32
- # <%= dynamic_image_tag( @blog_post.image, :size => "120x100", :filterset => 'blog_thumbnails' ) %>
33
- #
34
- # === Applying effects by default
35
- #
36
- # If <tt>Image.get_oricessed</tt> is called without filters, it will look for a set named 'default'.
37
- # This means that you can automatically apply effects on resized images by defining a class called <tt>DefaultFilterset</tt>:
38
- #
39
- # class DefaultFilterset < DynamicImage::Filterset
40
- # def self.process(image)
41
- # image = image.unsharp_mask # apply unsharp mask on images by default.
42
- # end
43
- # end
44
- #
45
- # === Chaining filters
46
- #
47
- # You can only apply one filterset on an image, but compound filters can easily be created:
48
- #
49
- # class CompoundFilterset < DynamicImage::Filterset
50
- # def self.process(image)
51
- # image = MyFirstFilterset.process(image)
52
- # image = SomeOtherFilterset.process(image)
53
- # image = DefaultFilterset.process(image)
54
- # end
55
- # end
56
- #
57
- class Filterset
58
- include ::Magick
5
+ @@filtersets = Hash.new
6
+
7
+ # Singleton methods for the filtersets hash.
8
+ class << @@filtersets
9
+ def names; keys; end
10
+ end
11
+
12
+ # Accessor for the filtersets hash. Installed filter names are available through the <tt>names</tt> method. Example:
13
+ # @filter_names = DynamicImage.filtersets.names
14
+ def self.filtersets
15
+ @@filtersets
16
+ end
17
+
18
+ # Base class for filter sets. Extending this with your own subclasses will automatically enable them for use.
19
+ # You'll need to overwrite <tt>Filterset.process</tt> in order to make your filter useful. Note that it's a class
20
+ # method.
21
+ #
22
+ # === Example
23
+ #
24
+ # class BlogThumbnailsFilterset < DynamicImage::Filterset
25
+ # def self.process(image)
26
+ # image = image.sepiatone # convert the image to sepia tones
27
+ # end
28
+ # end
29
+ #
30
+ # The filter set is now available for use in your application:
31
+ #
32
+ # <%= dynamic_image_tag( @blog_post.image, :size => "120x100", :filterset => 'blog_thumbnails' ) %>
33
+ #
34
+ # === Applying effects by default
35
+ #
36
+ # If <tt>Image.get_oricessed</tt> is called without filters, it will look for a set named 'default'.
37
+ # This means that you can automatically apply effects on resized images by defining a class called <tt>DefaultFilterset</tt>:
38
+ #
39
+ # class DefaultFilterset < DynamicImage::Filterset
40
+ # def self.process(image)
41
+ # image = image.unsharp_mask # apply unsharp mask on images by default.
42
+ # end
43
+ # end
44
+ #
45
+ # === Chaining filters
46
+ #
47
+ # You can only apply one filterset on an image, but compound filters can easily be created:
48
+ #
49
+ # class CompoundFilterset < DynamicImage::Filterset
50
+ # def self.process(image)
51
+ # image = MyFirstFilterset.process(image)
52
+ # image = SomeOtherFilterset.process(image)
53
+ # image = DefaultFilterset.process(image)
54
+ # end
55
+ # end
56
+ #
57
+ class Filterset
58
+ include ::Magick
59
59
 
60
- # Detect inheritance and store the new filterset in the lookup table.
61
- def self.inherited(sub)
62
- filter_name = sub.name.gsub!( /Filterset$/, '' ).underscore
63
- DynamicImage.filtersets[filter_name] = sub
64
- end
60
+ # Detect inheritance and store the new filterset in the lookup table.
61
+ def self.inherited(sub)
62
+ filter_name = sub.name.gsub!( /Filterset$/, '' ).underscore
63
+ DynamicImage.filtersets[filter_name] = sub
64
+ end
65
65
 
66
- # Get a Filterset class by name. Accepts a symbol or string, CamelCase and under_scores both work.
67
- def self.[](filter_name)
68
- filter_name = filter_name.to_s if filter_name.kind_of? Symbol
69
- filter_name = filter_name.underscore
70
- DynamicImage.filtersets[filter_name] || nil
71
- end
66
+ # Get a Filterset class by name. Accepts a symbol or string, CamelCase and under_scores both work.
67
+ def self.[](filter_name)
68
+ filter_name = filter_name.to_s if filter_name.kind_of? Symbol
69
+ filter_name = filter_name.underscore
70
+ DynamicImage.filtersets[filter_name] || nil
71
+ end
72
72
 
73
- # Process the image. This is a dummy method, you should overwrite it in your subclass.
74
- def self.process(image)
75
- # This is a stub
76
- end
77
-
78
- end
79
- end
73
+ # Process the image. This is a dummy method, you should overwrite it in your subclass.
74
+ def self.process(image)
75
+ # This is a stub
76
+ end
77
+
78
+ end
79
+ end
@@ -1,107 +1,107 @@
1
1
  require 'dynamic_image'
2
2
 
3
3
  module DynamicImage
4
- module Helper
5
-
6
- # Returns an hash consisting of the URL to the dynamic image and parsed options. This is mostly for internal use by
7
- # dynamic_image_tag and dynamic_image_url.
8
- def dynamic_image_options(image, options = {})
9
- options.symbolize_keys!
10
-
11
- options = {:crop => false}.merge(options)
12
- url_options = {:controller => "/images", :action => :render_dynamic_image, :id => image}
13
-
14
- if options[:original]
15
- url_options[:original] = 'original'
16
- options.delete(:original)
17
- end
18
-
19
- # Image sizing
20
- if options[:size]
21
- new_size = Vector2d.new(options[:size])
22
- image_size = Vector2d.new(image.size)
23
-
24
- unless options[:upscale]
25
- new_size.x = image_size.x if new_size.x > 0 && new_size.x > image_size.x
26
- new_size.y = image_size.y if new_size.y > 0 && new_size.y > image_size.y
27
- end
28
-
29
- unless options[:crop]
30
- new_size = image_size.constrain_both(new_size)
31
- end
32
-
33
- options[:size] = new_size.round.to_s
34
- url_options[:size] = options[:size]
35
- end
36
- options.delete :crop
37
-
38
- if options[:no_size_attr]
39
- options.delete :no_size_attr
40
- options.delete :size
41
- end
42
-
43
- # Filterset
44
- if options[:filterset]
45
- url_options[:filterset] = options[:filterset]
46
- options.delete :filterset
47
- end
48
-
49
- # Filename
50
- if options[:filename]
51
- filename = options[:filename]
52
- unless filename =~ /\.[\w]{1,4}$/
53
- filename += "." + image.filename.split(".").last
54
- end
55
- url_options[:filename] = filename
56
- else
57
- url_options[:filename] = image.filename
58
- end
59
-
60
- # Alt attribute
61
- options[:alt] ||= image.name if image.name?
62
- options[:alt] ||= image.filename.split('.').first.capitalize
63
-
64
- if options.has_key?(:only_path)
65
- url_options[:only_path] = options[:only_path]
66
- options[:only_path] = nil
67
- end
68
- if options.has_key?(:host)
69
- url_options[:host] = options[:host]
70
- options[:host] = nil
71
- end
72
-
73
- {:url => url_for(url_options), :options => options}
74
- end
75
-
76
- # Returns an image tag for the provided image model, works similar to the rails <tt>image_tag</tt> helper.
77
- #
78
- # The following options are supported (the rest will be forwarded to <tt>image_tag</tt>):
79
- #
80
- # * :size - Resize the image to fit these proportions. Size is given as a string with the format
81
- # '100x100'. Either dimension can be omitted, for example: '100x'
82
- # * :crop - Crop the image to the size given. (Boolean, default: <tt>false</tt>)
83
- # * :no_size_attr - Do not include width and height attributes in the image tag. (Boolean, default: false)
84
- # * :filterset - Apply the given filterset to the image
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]+/,'')
96
- end
97
-
98
- # Returns an url corresponding to the provided image model.
99
- # Special options are documented in ApplicationHelper.dynamic_image_tag, only <tt>:size</tt>, <tt>:filterset</tt> and <tt>:crop</tt> apply.
100
- def dynamic_image_url(image, options = {})
101
- parsed_options = dynamic_image_options(image, options)
102
- parsed_options[:url]
103
- end
104
- end
4
+ module Helper
5
+
6
+ # Returns an hash consisting of the URL to the dynamic image and parsed options. This is mostly for internal use by
7
+ # dynamic_image_tag and dynamic_image_url.
8
+ def dynamic_image_options(image, options = {})
9
+ options.symbolize_keys!
10
+
11
+ options = {:crop => false}.merge(options)
12
+ url_options = {:controller => "/images", :action => :render_dynamic_image, :id => image}
13
+
14
+ if options[:original]
15
+ url_options[:original] = 'original'
16
+ options.delete(:original)
17
+ end
18
+
19
+ # Image sizing
20
+ if options[:size]
21
+ new_size = Vector2d.new(options[:size])
22
+ image_size = Vector2d.new(image.size)
23
+
24
+ unless options[:upscale]
25
+ new_size.x = image_size.x if new_size.x > 0 && new_size.x > image_size.x
26
+ new_size.y = image_size.y if new_size.y > 0 && new_size.y > image_size.y
27
+ end
28
+
29
+ unless options[:crop]
30
+ new_size = image_size.constrain_both(new_size)
31
+ end
32
+
33
+ options[:size] = new_size.round.to_s
34
+ url_options[:size] = options[:size]
35
+ end
36
+ options.delete :crop
37
+
38
+ if options[:no_size_attr]
39
+ options.delete :no_size_attr
40
+ options.delete :size
41
+ end
42
+
43
+ # Filterset
44
+ if options[:filterset]
45
+ url_options[:filterset] = options[:filterset]
46
+ options.delete :filterset
47
+ end
48
+
49
+ # Filename
50
+ if options[:filename]
51
+ filename = options[:filename]
52
+ unless filename =~ /\.[\w]{1,4}$/
53
+ filename += "." + image.filename.split(".").last
54
+ end
55
+ url_options[:filename] = filename
56
+ else
57
+ url_options[:filename] = image.filename
58
+ end
59
+
60
+ # Alt attribute
61
+ options[:alt] ||= image.name if image.name?
62
+ options[:alt] ||= image.filename.split('.').first.capitalize
63
+
64
+ if options.has_key?(:only_path)
65
+ url_options[:only_path] = options[:only_path]
66
+ options[:only_path] = nil
67
+ end
68
+ if options.has_key?(:host)
69
+ url_options[:host] = options[:host]
70
+ options[:host] = nil
71
+ end
72
+
73
+ {:url => url_for(url_options), :options => options}
74
+ end
75
+
76
+ # Returns an image tag for the provided image model, works similar to the rails <tt>image_tag</tt> helper.
77
+ #
78
+ # The following options are supported (the rest will be forwarded to <tt>image_tag</tt>):
79
+ #
80
+ # * :size - Resize the image to fit these proportions. Size is given as a string with the format
81
+ # '100x100'. Either dimension can be omitted, for example: '100x'
82
+ # * :crop - Crop the image to the size given. (Boolean, default: <tt>false</tt>)
83
+ # * :no_size_attr - Do not include width and height attributes in the image tag. (Boolean, default: false)
84
+ # * :filterset - Apply the given filterset to the image
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
96
+ end
97
+
98
+ # Returns an url corresponding to the provided image model.
99
+ # Special options are documented in ApplicationHelper.dynamic_image_tag, only <tt>:size</tt>, <tt>:filterset</tt> and <tt>:crop</tt> apply.
100
+ def dynamic_image_url(image, options = {})
101
+ parsed_options = dynamic_image_options(image, options)
102
+ parsed_options[:url]
103
+ end
104
+ end
105
105
  end
106
106
 
107
- ActionView::Base.send(:include, DynamicImage::Helper)
107
+ ActionView::Base.send(:include, DynamicImage::Helper)