smartthumbs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ *.DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in smartthumbs.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Alexander Pauly
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.markdown ADDED
@@ -0,0 +1,63 @@
1
+ ## Smartthumbs
2
+
3
+ This Gem helps you create any kind of thumbnails on-the-fly.
4
+
5
+ ## Features
6
+ * define your various thumb-formats inside of your model and let smartthumbs do the rest.
7
+ * writes created thumbs to the public directory - every thumb is only created once and only if needed
8
+ * Works with blob-based records and filename-based records
9
+ * can be implemented in several models
10
+ * define which strategy should be used to resize your images
11
+
12
+ ## Install
13
+ Add the Gem and then create an initializer-script in config/initializers:
14
+
15
+ Smartthumbs::Config.run do |config|
16
+ config[:valid_classes] = ["Image"]
17
+ # optional
18
+ config[:assume_klass] = "Image"
19
+ end
20
+
21
+ Smartthumbs needs to know all classes that you want to use smartthumbs with.
22
+ Pass them as an array of strings via :valid_classes .
23
+
24
+ By default smartthumbs generates urls like "/th/<klass-name>/<format>/<record-id>.<extension>". If you only have a single class you can set the default-class and prevent this class name from appering in that url.
25
+
26
+
27
+ ## Examples
28
+
29
+ ### In your models
30
+ class Image < ActiveRecord::Base
31
+ smartthumbs :file => :file_path, :extension => "jpg", :formats => {
32
+ "thumb" => ["800x200", :cut, :w],
33
+ "small" => ["100x100", :fit],
34
+ "tiny" => ["15x15", :fill]
35
+ }
36
+
37
+ def file_path
38
+ "#{Rails.root}/tmp/uploads/#{self.id}.jpg"
39
+ end
40
+ end
41
+
42
+
43
+
44
+ class Image < ActiveRecord::Base
45
+ smartthumbs :blob => :db_blob_column, :extension => :my_extension, :formats => {
46
+ "thumb" => ["800x100", :fit, :e]
47
+ }
48
+
49
+ def my_extension
50
+ "jpg"
51
+ end
52
+ end
53
+
54
+ ### In your View
55
+
56
+ <%= thumb_tag, @image, "tiny", :class => "red-border" %>
57
+
58
+ will generate something like:
59
+
60
+ <img src="/th/my_image/tiny/5.jpg" class="red-border"/>
61
+
62
+
63
+ Copyright (c) 2011 Alexander Pauly, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,35 @@
1
+ class ThumbsController < ApplicationController
2
+
3
+ require 'RMagick'
4
+ include Magick
5
+
6
+ def deliver_crop
7
+ klass, format, id = parse_params
8
+
9
+ @obj = klass.find(id)
10
+ @obj.create_thumb_for(format)
11
+
12
+ send_file(@obj.thumb_path_for(format), :type => 'image/jpeg', :disposition => 'inline')
13
+ end
14
+
15
+ private
16
+ def parse_params
17
+ parsed = params[:path].split(".")[0..-2].first.split("/")
18
+
19
+ if parsed.length < 3 && Smartthumbs::Config.options[:assume_klass].present?
20
+ parsed.unshift(
21
+ Smartthumbs::Config.options[:assume_klass]
22
+ )
23
+ else
24
+ parsed[0] = parsed.first.gsub("-", "/").classify
25
+ end
26
+
27
+ unless Smartthumbs::Config.options[:valid_classes].include?(parsed[0])
28
+ raise "Bad Request"
29
+ else
30
+ parsed[0] = parsed.first.constantize
31
+ end
32
+ parsed
33
+ end
34
+
35
+ end
@@ -0,0 +1,7 @@
1
+ module SmartthumbsHelper
2
+
3
+ def thumb_tag(record, format, opts={})
4
+ image_tag record.thumb_url_for(format), opts
5
+ end
6
+
7
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails::Application.routes.draw do
2
+ match '/th/*path', :controller => "thumbs", :action => "deliver_crop"
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'smartthumbs'
2
+ require 'rails'
3
+ require 'action_controller'
4
+
5
+ #http://www.themodestrubyist.com/2010/03/05/rails-3-plugins---part-2---writing-an-engine/
6
+
7
+ module Smartthumbs
8
+ class Engine < Rails::Engine
9
+ config.to_prepare do
10
+ ApplicationController.helper("Smartthumbs")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,141 @@
1
+ module Smartthumbs
2
+
3
+ module Thumbable
4
+ require 'RMagick'
5
+ include Magick
6
+
7
+ # return the rmagick instance
8
+ def rmagick_img
9
+ if self.class.st_config[:blob].present?
10
+ @rmagick_img ||= Magick::ImageList.new.from_blob(
11
+ self.send(self.class.st_config[:blob])
12
+ ).first
13
+ elsif self.class.st_config[:file].present?
14
+ @rmagick_img ||= Magick::ImageList.new.from_blob(
15
+ File.read(self.send(self.class.st_config[:file]))
16
+ ).first
17
+ else
18
+ raise "No thumb source defined. You have to define neither :blob or :file"
19
+ end
20
+ end
21
+
22
+ # returns all possible @formats for the current image
23
+ def st_format(f)
24
+ self.class.st_config[:formats][f]
25
+ end
26
+
27
+ # returns the file extension for the current image
28
+ def st_extension
29
+ return "jpg" unless self.class.st_config[:extension].present?
30
+ if self.class.st_config[:extension].is_a?(String)
31
+ self.class.st_config[:extension]
32
+ else
33
+ self.send(self.class.st_config[:extension])
34
+ end
35
+ end
36
+
37
+ # creates the directory for a certain @format if it doesn't exist
38
+ def create_directory
39
+ dest = File.dirname(thumb_path_for(@format))
40
+ FileUtils.mkdir_p(dest) unless File.exists?(dest)
41
+ end
42
+
43
+ # Creates the thumb for a certain @format
44
+ def create_thumb_for(format)
45
+ @format = format
46
+ return if st_format(@format).blank?
47
+
48
+ create_directory
49
+
50
+ method = st_format(@format)[1] || :cut
51
+ @x, @y = st_format(@format).first.split("x").map(&:to_i)
52
+
53
+ if self.respond_to?(method)
54
+ self.send(method)
55
+ end
56
+
57
+ rounding_error
58
+ rmagick_img.write(thumb_path_for(@format)) { self.quality = 80 }
59
+ nil
60
+ end
61
+
62
+ # returns the gravity for the current resizing process and
63
+ # provides some shrotcuts
64
+ def gravity
65
+ return Magick::CenterGravity unless (st_format(@format) || []).length >= 3
66
+ {
67
+ :new => Magick::NorthWestGravity,
68
+ :n => Magick::NorthGravity,
69
+ :ne => Magick::NorthEastGravity,
70
+ :w => Magick::WestGravity,
71
+ :c => Magick::CenterGravity,
72
+ :e => Magick::EastGravity,
73
+ :sw => Magick::SouthWestGravity,
74
+ :s => Magick::SouthGravity,
75
+ :se => Magick::SouthEastGravity
76
+ }[st_format(@format).last]
77
+ end
78
+
79
+ # Does a thumb already exist?
80
+ def thumb_exists_for?(format)
81
+ File.exists?(self.thumb_path_for(format))
82
+ end
83
+
84
+ # returns the cache-path for a certain image
85
+ def thumb_path_for(format)
86
+ "#{Rails.root}/public#{thumb_url_for(format)}"
87
+ end
88
+
89
+ # return the http url to the resized image
90
+ # this one has to be route from which the image is
91
+ # availabe - otherwise the caching benefit is gone
92
+ def thumb_url_for(format)
93
+ if Smartthumbs::Config.options[:assume_klass] == self.class.to_s
94
+ "/th/#{format.to_s}/#{self.id}.#{st_extension}"
95
+ else
96
+ "/th/#{self.class.to_s.underscore.parameterize}/#{format.to_s}/#{self.id}.#{st_extension}"
97
+ end
98
+ end
99
+
100
+ # resizes the image in a manner that both edges fit the needs.
101
+ # usually one of the edges is smaller than the needs afterwards
102
+ def fit
103
+ if self.needs_to_be_resized?
104
+ rmagick_img.resize_to_fit!(@x, @y)
105
+ else
106
+ rmagick_img.resize_to_fit(@x, @y)
107
+ end
108
+ end
109
+
110
+ # the same as +fit+, except the fact that the image
111
+ # get's filled up with a border
112
+ def fill
113
+ fit
114
+ rounding_error
115
+ border_x = (@x - rmagick_img.columns)/2
116
+ border_y = (@y - rmagick_img.rows)/2
117
+
118
+ rmagick_img.border!(border_x,border_y,"white")
119
+ end
120
+
121
+ # resizes and cuts the image, so it that it fits exactly
122
+ def cut
123
+ rmagick_img.crop_resized!(@x, @y, gravity)
124
+ end
125
+
126
+ # if there's just a small difference between the needs and the result,
127
+ # we'll make it fit exaclty
128
+ def rounding_error
129
+ dif = (@y-rmagick_img.rows) + (@x-rmagick_img.columns)
130
+
131
+ if dif > 0 && dif < 10 then
132
+ rmagick_img.resize!(@x, @y)
133
+ end
134
+ end
135
+
136
+ # checks whether the image needs to be resized to fit the current @format or not
137
+ def needs_to_be_resized?
138
+ rmagick_img.rows > @y || rmagick_img.columns > @x
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,3 @@
1
+ module Smartthumbs
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,31 @@
1
+ module Smartthumbs
2
+ require 'smartthumbs/engine' if defined?(Rails)
3
+
4
+ module ActiceRecord
5
+ module ClassMethods
6
+ attr_accessor :st_config
7
+ def smartthumbs(opts={})
8
+ self.st_config = opts
9
+ self.send(:include, Smartthumbs::Thumbable)
10
+ end
11
+ end
12
+
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+ end
17
+
18
+ class Config
19
+ class << self
20
+ attr_accessor :options
21
+ def run
22
+ self.options ||= {}
23
+ yield self.options
24
+ end
25
+ end
26
+ end
27
+
28
+ require "smartthumbs/thumbable"
29
+ ::ActiveRecord::Base.send(:include, Smartthumbs::ActiceRecord)
30
+
31
+ end
@@ -0,0 +1,15 @@
1
+ namespace :smartthumbs do
2
+
3
+ desc "Delte all created thumbs"
4
+ task :delete_all do
5
+ `rm -rf #{Rails.root}/public/th`
6
+ end
7
+
8
+ desc "delete all thumbs that are older than 1 day"
9
+ task :delete_old do
10
+ Dir["#{Rails.root}/public/th/**/**/*.jpg"].each do |f|
11
+ File.delete(f) if File.mtime(f) < 1.day.ago
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "smartthumbs/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "smartthumbs"
7
+ s.version = Smartthumbs::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Alexander Pauly"]
10
+ s.email = ["railsninja@gmx.net"]
11
+ s.homepage = "http://rubygems.org/gems/smartthumbs"
12
+ s.summary = %q{Smart on-the-fly thumbnail creation for blob or filesystem based images}
13
+ s.description = %q{Smartthumbs let's you define several different formats. By default, every image is available in any format. Once a thumb is requested, it will be generated on the fly and then be saved to the public directory. The next user who accesses the image will get the static image from disk.'}
14
+
15
+ s.rubyforge_project = "smartthumbs"
16
+
17
+ s.add_dependency 'rmagick'
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smartthumbs
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Alexander Pauly
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-22 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rmagick
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: Smartthumbs let's you define several different formats. By default, every image is available in any format. Once a thumb is requested, it will be generated on the fly and then be saved to the public directory. The next user who accesses the image will get the static image from disk.'
36
+ email:
37
+ - railsninja@gmx.net
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - .gitignore
46
+ - Gemfile
47
+ - MIT-LICENSE
48
+ - README.markdown
49
+ - Rakefile
50
+ - app/controllers/thumbs_controller.rb
51
+ - app/helpers/smartthumbs_helper.rb
52
+ - config/routes.rb
53
+ - lib/smartthumbs.rb
54
+ - lib/smartthumbs/engine.rb
55
+ - lib/smartthumbs/thumbable.rb
56
+ - lib/smartthumbs/version.rb
57
+ - lib/tasks/smartthumbs.rake
58
+ - smartthumbs.gemspec
59
+ has_rdoc: true
60
+ homepage: http://rubygems.org/gems/smartthumbs
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ hash: 3
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project: smartthumbs
89
+ rubygems_version: 1.3.7
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Smart on-the-fly thumbnail creation for blob or filesystem based images
93
+ test_files: []
94
+