rai 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7535f625055b6e362e4d80005c52b8e7052a5249
4
+ data.tar.gz: ba478f0a4db98ab3bae31376c50f4ce75b7a6fea
5
+ SHA512:
6
+ metadata.gz: 4fe859a9caaeaeee7e74d30237a0683693e7ff96e98bbc26daad5747a3c93f40be9badd2ec11309a6e21128e348c4b7c27d894f6c8fe6034b6f2a6d76b958df1
7
+ data.tar.gz: 5886575aeec57e804270c67628b9daa0531a4bcabe5a3be74b34e68839f97fbd89a37cb3c74bee36cbeadc3d2ec7b8b0eb7ed6e1fea2bce02822f2fd5149beb2
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ pkg
3
+ *.cache
4
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'sinatra'
4
+ gem 'mini_magick'
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Ruby Adaptive-Images
2
+ This is a ruby port of Adaptive-Images (http://adaptive-images.com/, originally by Matt Wilcox).
3
+
4
+ It runs as a sinatra application that can be mounted using Rack.
5
+
6
+ # Author
7
+ Kim Nørgaard <jasen@jasen.dk>
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
+ require "rai/version"
3
+ require 'bundler/gem_tasks'
4
+
5
+ #task :build do
6
+ # system "gem build rai.gemspec"
7
+ #end
8
+
9
+ #task :release => :build do
10
+ # system "gem push rai-#{RAI::VERSION}.gem"
11
+ #end
data/config.ru ADDED
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+ require 'rai'
3
+
4
+ map('/photos') { run Rai::App }
@@ -0,0 +1,3 @@
1
+ module Rai
2
+ VERSION = '0.0.1'
3
+ end
data/lib/rai.rb ADDED
@@ -0,0 +1,146 @@
1
+ require 'sinatra'
2
+ require 'mini_magick'
3
+ require 'fileutils'
4
+
5
+ module Rai
6
+ class App < Sinatra::Base
7
+ # keep an eye on the cache to see if it needs updating
8
+ set :watch_cache, true
9
+ # resolution break-points (screen widths)
10
+ set :resolutions, [1382, 992, 768, 480, 320]
11
+ # jpg compression ratio, 0-100
12
+ set :jpg_quality, 75
13
+ # wether image should be sharpened or not
14
+ set :sharpen, true
15
+ # 7 days
16
+ set :cache_max_age, 60*60*24*7
17
+ # where images are placed
18
+ set :img_path, File.join(File.dirname(__FILE__), 'images')
19
+ # where cached versions are placed
20
+ set :cache_path, File.join(File.dirname(__FILE__), 'images', 'cache')
21
+
22
+ get %r{.*?\.(jpg|jpeg|png|gif)$} do
23
+ @img_file = File.join(settings.img_path, @request_path)
24
+ not_found unless File.exists? @img_file
25
+ @cache_file = File.join(settings.cache_path, @resolution.to_s, @request_path)
26
+ @extension = params[:captures][0].downcase
27
+
28
+ expires settings.cache_max_age, :private, :must_revalidate
29
+
30
+ if File.exists? @cache_file
31
+ refresh_cache
32
+ else
33
+ update_cached_image
34
+ end
35
+ send_file @cache_file
36
+ end
37
+
38
+ before do
39
+ @request_path = URI.decode(request.path_info)
40
+ settings.resolutions.sort!{|x,y| y <=> x }
41
+ @resolution = get_resolution
42
+ end
43
+
44
+ helpers do
45
+ def get_resolution
46
+ get_resolution_from_cookie || get_resolution_from_user_agent
47
+ end
48
+
49
+ def get_resolution_from_cookie
50
+ if res_cookie = request.cookies['resolution']
51
+ cookie_data = res_cookie.split(',')
52
+ total_width = client_width = cookie_data[0].to_i
53
+ # the device's pixel density factor (physical pixels per CSS pixel)
54
+ pixel_density = cookie_data[1] ? cookie_data[1].to_i : 1
55
+ # by default use the largest supported break-point
56
+ resolution = settings.resolutions.first
57
+
58
+ if pixel_density != 1
59
+ total_width = client_width * pixel_density
60
+ end
61
+
62
+ resolution =
63
+ settings.resolutions.select {|res| total_width <= res}.last
64
+ resolution ||= settings.resolutions.first
65
+
66
+ if total_width > settings.resolutions.first
67
+ resolution *= pixel_density
68
+ end
69
+
70
+ return resolution
71
+ end
72
+ end
73
+
74
+ def get_resolution_from_user_agent
75
+ is_mobile ? settings.resolutions.min : settings.resolutions.max
76
+ end
77
+
78
+ def is_mobile
79
+ request.user_agent.downcase.match(/mobile/)
80
+ end
81
+
82
+ def refresh_cache
83
+ return unless settings.watch_cache
84
+ return if File.mtime(@cache_file) >= File.mtime(@img_file)
85
+
86
+ File.delete @cache_file
87
+ update_cached_image
88
+ end
89
+
90
+ def update_cached_image
91
+ cache_dir = File.dirname(@cache_file)
92
+ begin
93
+ #Dir.mkdir(settings.cache_path, 0755) unless File.directory?(settings.cache_path)
94
+ FileUtils.mkdir_p(cache_dir, :mode => 0755) unless File.directory?(cache_dir)
95
+ rescue SystemCallError => e
96
+ halt(500, "Unable to create caching directory. #{e}")
97
+ rescue => e
98
+ halt(500, "Unable to create caching directory. #{e}")
99
+ end
100
+
101
+ begin
102
+ image = MiniMagick::Image.open(@img_file)
103
+ rescue Exception => e
104
+ halt(500, "Error loading image: #{e}")
105
+ end
106
+
107
+ # Do we need to downscale the image?
108
+ if image[:width] <= @resolution
109
+ @cache_file = @img_file
110
+ return
111
+ end
112
+
113
+ ratio = image["%[fx:w/h]"].to_f
114
+ new_width = @resolution
115
+ new_height = (new_width*ratio).ceil
116
+
117
+ if @extension == 'jpg'
118
+ image.combine_options do |c|
119
+ c.interlace 'plane'
120
+ c.quality settings.jpg_quality
121
+ end
122
+ end
123
+
124
+ if settings.sharpen
125
+ radius = 0.5
126
+ sigma = 0.5
127
+ amount = 1.0
128
+ threshold = 0.02
129
+ image.unsharp "#{radius}x#{sigma}+#{amount}+#{threshold}"
130
+ end
131
+
132
+ image.resize "#{new_width}x#{new_height}"
133
+
134
+ begin
135
+ image.write @cache_file
136
+ rescue Exception => e
137
+ halt(500, "Error writing cache file: #{e}")
138
+ end
139
+ end
140
+ end
141
+
142
+ not_found do
143
+ "Not found: #{@request_path} not found."
144
+ end
145
+ end
146
+ end
data/rai.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rai/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rai'
7
+ s.version = Rai::VERSION
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
+ s.authors = ["Kim Nørgaard"]
10
+ s.description = 'Ruby-port of Adaptive Images (http://adaptive-images.com/)'
11
+ s.summary = 'Scales images according to screen width'
12
+ s.email = 'jasen@jasen.dk'
13
+ s.homepage = %q{https://github.com/KimNorgaard/rai}
14
+ s.licenses = 'Creative Commons Attribution 3.0 Unported License'
15
+
16
+ s.add_runtime_dependency 'sinatra'
17
+ s.add_runtime_dependency 'mini_magick'
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.require_paths = ["lib"]
21
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rai
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kim Nørgaard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mini_magick
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Ruby-port of Adaptive Images (http://adaptive-images.com/)
42
+ email: jasen@jasen.dk
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - README.md
50
+ - Rakefile
51
+ - config.ru
52
+ - lib/rai.rb
53
+ - lib/rai/version.rb
54
+ - rai.gemspec
55
+ homepage: https://github.com/KimNorgaard/rai
56
+ licenses:
57
+ - Creative Commons Attribution 3.0 Unported License
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 2.0.3
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: Scales images according to screen width
79
+ test_files: []