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
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'dynamic_image'
|
data/install.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Install hook code here
|
@@ -1,144 +0,0 @@
|
|
1
|
-
require 'binary_storage'
|
2
|
-
|
3
|
-
module BinaryStorage
|
4
|
-
module ActiveRecordExtensions
|
5
|
-
|
6
|
-
def self.included(base)
|
7
|
-
base.send(:extend, BinaryStorage::ActiveRecordExtensions::ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
|
12
|
-
def register_binary(klass, binary_name, binary_column)
|
13
|
-
@@binary_columns ||= {}
|
14
|
-
@@binary_columns[klass] ||= {}
|
15
|
-
@@binary_columns[klass][binary_name] = binary_column
|
16
|
-
end
|
17
|
-
|
18
|
-
def binary_column(klass, binary_name)
|
19
|
-
if @@binary_columns && @@binary_columns[klass] && @@binary_columns[klass][binary_name]
|
20
|
-
@@binary_columns[klass][binary_name]
|
21
|
-
else
|
22
|
-
nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Count existing references to a binary
|
27
|
-
def binary_reference_count(hash_string)
|
28
|
-
references = 0
|
29
|
-
if @@binary_columns
|
30
|
-
@@binary_columns.each do |klass, binaries|
|
31
|
-
binaries.each do |binary_name, binary_column|
|
32
|
-
references += klass.count(:all, :conditions => ["`#{binary_column} = ?`", hash_string])
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def binary_storage(binary_name, binary_column)
|
39
|
-
binary_name = binary_name.to_s
|
40
|
-
binary_column = binary_column.to_s
|
41
|
-
|
42
|
-
register_binary(self, binary_name, binary_column)
|
43
|
-
|
44
|
-
class_eval <<-end_eval
|
45
|
-
before_save do |binary_model|
|
46
|
-
binary_model.save_binary("#{binary_name}")
|
47
|
-
end
|
48
|
-
|
49
|
-
after_destroy do |model|
|
50
|
-
binary_model.destroy_binary("#{binary_name}")
|
51
|
-
end
|
52
|
-
|
53
|
-
def #{binary_name}
|
54
|
-
self.get_binary_data("#{binary_name}")
|
55
|
-
end
|
56
|
-
|
57
|
-
def #{binary_name}=(binary_data)
|
58
|
-
self.set_binary_data("#{binary_name}", binary_data)
|
59
|
-
end
|
60
|
-
|
61
|
-
def #{binary_name}?
|
62
|
-
self.has_binary_data?("#{binary_name}")
|
63
|
-
end
|
64
|
-
end_eval
|
65
|
-
|
66
|
-
send(:include, BinaryStorage::ActiveRecordExtensions::InstanceMethods)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
module InstanceMethods
|
71
|
-
|
72
|
-
def binaries
|
73
|
-
@binaries ||= {}
|
74
|
-
end
|
75
|
-
|
76
|
-
def binary_column(binary_name)
|
77
|
-
if column_name = self.class.binary_column(self.class, binary_name)
|
78
|
-
column_name
|
79
|
-
else
|
80
|
-
raise "Binary column #{binary_name} not defined!"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def binary_hash_string(binary_name)
|
85
|
-
self.attributes[binary_column(binary_name)]
|
86
|
-
end
|
87
|
-
|
88
|
-
def save_binary(binary_name)
|
89
|
-
if binaries.has_key?(binary_name)
|
90
|
-
if binary = binaries[binary_name]
|
91
|
-
binary.save
|
92
|
-
self.attributes = self.attributes.merge({binary_column(binary_name).to_sym => binary.hash_string})
|
93
|
-
else
|
94
|
-
self.attributes = self.attributes.merge({binary_column(binary_name).to_sym => nil})
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def destroy_binary(binary_name)
|
100
|
-
if binary = binaries[binary_name]
|
101
|
-
if hash_string = binary.hash_string
|
102
|
-
references = self.class.binary_reference_count
|
103
|
-
if references < 1
|
104
|
-
binary.delete!
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def get_binary_data(binary_name)
|
111
|
-
# Set directly?
|
112
|
-
if binary = binaries[binary_name]
|
113
|
-
binary.data
|
114
|
-
|
115
|
-
# Try loading
|
116
|
-
elsif hash_string = binary_hash_string(binary_name)
|
117
|
-
if binary = BinaryStorage::Blob.find(hash_string)
|
118
|
-
binaries[binary_name] = binary # Cache it
|
119
|
-
binary.data
|
120
|
-
else
|
121
|
-
nil
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def set_binary_data(binary_name, binary_data)
|
127
|
-
binary = (binary_data) ? BinaryStorage::Blob.new(binary_data) : nil
|
128
|
-
binaries[binary_name] = binary
|
129
|
-
end
|
130
|
-
|
131
|
-
def has_binary_data?(binary_name)
|
132
|
-
if binaries[binary_name]
|
133
|
-
true
|
134
|
-
else
|
135
|
-
hash_string = binary_hash_string(binary_name)
|
136
|
-
(hash_string && BinaryStorage::Blob.exists?(hash_string)) ? true : false
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
ActiveRecord::Base.send(:include, BinaryStorage::ActiveRecordExtensions)
|
data/lib/binary_storage/blob.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
module BinaryStorage
|
2
|
-
class Blob
|
3
|
-
|
4
|
-
class << self
|
5
|
-
def find(hash_string)
|
6
|
-
blob = self.new(:hash_string => hash_string)
|
7
|
-
return nil unless blob.exists?
|
8
|
-
blob.load
|
9
|
-
blob
|
10
|
-
end
|
11
|
-
|
12
|
-
def exists?(hash_string)
|
13
|
-
self.new(:hash_string => hash_string).exists?
|
14
|
-
end
|
15
|
-
|
16
|
-
def create(data)
|
17
|
-
blob = self.new(data)
|
18
|
-
blob.save
|
19
|
-
blob
|
20
|
-
end
|
21
|
-
|
22
|
-
def storage_dir(hash_string=nil)
|
23
|
-
root = BinaryStorage.storage_dir
|
24
|
-
(hash_string) ? File.join(root, hash_string.match(/^(..)/)[1]) : root
|
25
|
-
end
|
26
|
-
|
27
|
-
def storage_path(hash_string)
|
28
|
-
File.join(storage_dir(hash_string), hash_string.gsub(/^(..)/, ''))
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def initialize(*args)
|
33
|
-
options = {
|
34
|
-
:hash_string => nil,
|
35
|
-
:data => nil
|
36
|
-
}
|
37
|
-
if args.first.kind_of?(Hash)
|
38
|
-
options.merge!(args.first)
|
39
|
-
else
|
40
|
-
options[:data] = args.first
|
41
|
-
end
|
42
|
-
@hash_string = options[:hash_string]
|
43
|
-
@data = options[:data]
|
44
|
-
end
|
45
|
-
|
46
|
-
def data
|
47
|
-
@data
|
48
|
-
end
|
49
|
-
|
50
|
-
def data=(new_data)
|
51
|
-
@hash_string = nil
|
52
|
-
@data = new_data
|
53
|
-
end
|
54
|
-
|
55
|
-
def hash_string
|
56
|
-
unless @hash_string
|
57
|
-
if @data
|
58
|
-
@hash_string = BinaryStorage.hexdigest(data)
|
59
|
-
else
|
60
|
-
raise "Binary has no data!"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
@hash_string
|
64
|
-
end
|
65
|
-
|
66
|
-
def storage_dir
|
67
|
-
BinaryStorage::Blob.storage_dir(hash_string)
|
68
|
-
end
|
69
|
-
|
70
|
-
def storage_path
|
71
|
-
BinaryStorage::Blob.storage_path(hash_string)
|
72
|
-
end
|
73
|
-
|
74
|
-
def exists?
|
75
|
-
File.exists?(storage_path)
|
76
|
-
end
|
77
|
-
|
78
|
-
def empty?
|
79
|
-
(hash_string && !exists?) || !data || data.empty?
|
80
|
-
end
|
81
|
-
|
82
|
-
def load
|
83
|
-
raise "File not found" unless exists?
|
84
|
-
@data = File.open(storage_path, "rb") {|io| io.read }
|
85
|
-
end
|
86
|
-
|
87
|
-
def delete
|
88
|
-
if exists?
|
89
|
-
FileUtils.rm(storage_path)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def save
|
94
|
-
unless exists?
|
95
|
-
FileUtils.mkdir_p(storage_dir)
|
96
|
-
file = File.new(storage_path, 'wb')
|
97
|
-
file.write(@data)
|
98
|
-
file.close
|
99
|
-
end
|
100
|
-
return true
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
end
|
data/lib/binary_storage.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'tempfile'
|
2
|
-
require 'digest/sha1'
|
3
|
-
|
4
|
-
require 'rails'
|
5
|
-
require 'active_record'
|
6
|
-
|
7
|
-
require File.join(File.dirname(__FILE__), 'binary_storage/active_record_extensions')
|
8
|
-
require File.join(File.dirname(__FILE__), 'binary_storage/blob')
|
9
|
-
|
10
|
-
module BinaryStorage
|
11
|
-
class << self
|
12
|
-
def storage_dir
|
13
|
-
@@storage_dir ||= Rails.root.join('db/binary_storage', Rails.env)
|
14
|
-
end
|
15
|
-
|
16
|
-
def storage_dir=(new_storage_dir)
|
17
|
-
@@storage_dir = new_storage_dir
|
18
|
-
end
|
19
|
-
|
20
|
-
def hexdigest_file(path)
|
21
|
-
Digest::SHA1.file(path).hexdigest
|
22
|
-
end
|
23
|
-
|
24
|
-
def hexdigest(string)
|
25
|
-
Digest::SHA1.hexdigest(string)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'dynamic_image'
|
2
|
-
|
3
|
-
module DynamicImage
|
4
|
-
module ActiveRecordExtensions
|
5
|
-
|
6
|
-
def self.included(base)
|
7
|
-
base.send :extend, ClassMethods
|
8
|
-
end
|
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
|
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
|
50
|
-
|
51
|
-
send :include, DynamicImage::ActiveRecordExtensions::InstanceMethods
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
module InstanceMethods
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
ActiveRecord::Base.send(:include, DynamicImage::ActiveRecordExtensions)
|
data/lib/dynamic_image/engine.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'dynamic_image'
|
2
|
-
|
3
|
-
module DynamicImage
|
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
|
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
|
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
|
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
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# Rails 2: class DynamicImageGenerator < Rails::Generator::NamedBase
|
2
|
-
|
3
|
-
require 'rails/generators'
|
4
|
-
require 'rails/generators/migration'
|
5
|
-
|
6
|
-
class DynamicImageGenerator < Rails::Generators::Base
|
7
|
-
|
8
|
-
include Rails::Generators::Migration
|
9
|
-
|
10
|
-
class << self
|
11
|
-
def source_root
|
12
|
-
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
13
|
-
end
|
14
|
-
|
15
|
-
def next_migration_number(dirname)
|
16
|
-
if ActiveRecord::Base.timestamped_migrations
|
17
|
-
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
18
|
-
else
|
19
|
-
"%.3d" % (current_migration_number(dirname) + 1)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
def migrations
|
26
|
-
migration_template 'migrations/create_images.rb', 'db/migrate/create_images.rb'
|
27
|
-
end
|
28
|
-
|
29
|
-
# def manifest
|
30
|
-
# record do |m|
|
31
|
-
# #m.file 'controllers/images_controller.rb', 'app/controllers/images_controller.rb'
|
32
|
-
# #m.file 'models/image.rb', 'app/models/image.rb'
|
33
|
-
# #m.file 'models/binary.rb', 'app/models/binary.rb'
|
34
|
-
# m.file 'migrations/20090909231629_create_binaries.rb', 'db/migrate/20090909231629_create_binaries.rb'
|
35
|
-
# m.file 'migrations/20090909231630_create_images.rb', 'db/migrate/20090909231630_create_images.rb'
|
36
|
-
# end
|
37
|
-
# end
|
38
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
class CreateImages < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :images do |t|
|
4
|
-
t.column :name, :string
|
5
|
-
t.column :filename, :string
|
6
|
-
t.column :content_type, :string
|
7
|
-
t.column :original_size, :string
|
8
|
-
t.column :hotspot, :string
|
9
|
-
t.column :sha1_hash, :string
|
10
|
-
t.column :cropped, :boolean, :null => false, :default => false
|
11
|
-
t.column :crop_start, :string
|
12
|
-
t.column :crop_size, :string
|
13
|
-
t.column :created_at, :datetime
|
14
|
-
t.column :updated_at, :datetime
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.down
|
19
|
-
drop_table :images
|
20
|
-
end
|
21
|
-
end
|
data/uninstall.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Uninstall hook code here
|