rai 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e3e45323e085e138807ed68cb37d8c59d02b7d0
4
- data.tar.gz: 8a23e4f8448d84c90cabb0f5e1eb501977c1a0d1
3
+ metadata.gz: fbd2639a30affd2ab6bb5e765ceaba2f712227dd
4
+ data.tar.gz: 4b18403ea39077a3bae28c3bc3f515d2223fd8ad
5
5
  SHA512:
6
- metadata.gz: 11b1deacc4d2fff0b5fedd45fabff32391df3759a5216ddd716aeebff6da7ba77c7375218cd529142fde08d0d0230edc5246e1578d0a7c6802e19b841154b4c7
7
- data.tar.gz: f430662073ad9123d3b5b9c47ad25b106b44e0431c54a7289d43950279a465bfb4841fe6ade4e0cee1ede3292d0531de7682e0d82e5db356e0f0620b87c383bd
6
+ metadata.gz: 02914b17f67e9081d661d1b0f30241c0b16385847d8c29aa327695bbd741a437b7226c0391132060d19c18b5af65e25091f03ef504e29ce6796c716df7ee2dfe
7
+ data.tar.gz: 09daca9694b60a4af3d7ed8cc28ded965d155827970f5d01499e7a129505dccbd1beebafc6bb254ebf63a54bd6f81a9fceef4cc6bbde418729f8ebf154b291c0
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  pkg
3
3
  *.cache
4
4
  Gemfile.lock
5
+ config.ru
data/README.md CHANGED
@@ -1,20 +1,23 @@
1
1
  # Ruby Adaptive-Images
2
- This is a ruby port of Adaptive-Images (http://adaptive-images.com/, originally by Matt Wilcox). It does not contain all features, but it does more or less the same in the same way. It uses ImageMagick (via mini_magick) in stead of GD.
2
+ This is a ruby port of Adaptive-Images (http://adaptive-images.com/,
3
+ originally by Matt Wilcox). It does not contain all features, but it does more
4
+ or less the same in the same way. It uses ImageMagick (via mini\_magick) in
5
+ stead of GD.
3
6
 
4
7
  It runs as a sinatra application that can be mounted using Rack.
5
8
 
6
9
  # Installation
7
10
 
8
- To install, run: `gem install rai`
11
+ `gem install rai`
9
12
 
10
13
  # Configuration
11
14
 
12
15
  Put something like this in your config.ru:
13
16
 
14
- ```
17
+ ```ruby
15
18
  require 'rai'
16
19
 
17
- map '/gallery' do
20
+ map '/images' do
18
21
  Rai::App.set :img_path, '/path/to/your/images'
19
22
  Rai::App.set :cache_path, '/path/to/your/cache'
20
23
  run Rai::App
@@ -24,40 +27,61 @@ end
24
27
 
25
28
  ## Settings
26
29
 
27
- ### :watch_cache
30
+ ### :watch\_cache
28
31
  Keep an eye on the cache to see if it needs updating.
32
+
29
33
  Values: true/false
34
+
30
35
  Default: true
31
36
 
32
37
  ### :resolutions
33
38
  Resolution break-points (screen widths).
39
+
34
40
  Value: array
35
- Default: [1382, 992, 768, 480, 320]
36
41
 
37
- ### :jpg_quality
42
+ Default: [2560, 1920, 1440, 1024, 768, 480]
43
+
44
+ ### :jpg\_quality
38
45
  JPG compression ratio, 0-100.
46
+
39
47
  Value: integer, 0-100
40
- Default: 75
48
+
49
+ Default: 85
41
50
 
42
51
  ### :sharpen
43
52
  Wether image should be sharpened or not.
53
+
44
54
  Value: true/false
55
+
45
56
  Default: true
46
57
 
47
- ### :cache_max_age
58
+ ### :cache\_max\_age
48
59
  Browser cache TTL
60
+
49
61
  Value: integer, seconds
62
+
50
63
  Default: 60*60*24*7 (7 days)
51
64
 
52
- ### :img_path
65
+ ### :img\_path
53
66
  Where images are placed.
67
+
54
68
  Value: string, path
55
- Default:File.join(File.dirname(__FILE__), 'images')
56
69
 
57
- ### :cache_path
70
+ Default:File.join(File.dirname(__FILE__), '..', 'images')
71
+
72
+ ### :cache\_path
58
73
  Where cached versions are placed.
74
+
59
75
  Value: string, path
60
- Default: File.join(File.dirname(__FILE__), 'images', 'cache')
76
+
77
+ Default: File.join(File.dirname(__FILE__), '..', 'images', 'rai-cache')
78
+
79
+ ### :cookie\_name
80
+ The name of the resolution cookie.
81
+
82
+ Value: string
83
+
84
+ Default: rai-resolution
61
85
 
62
86
  # Author
63
87
  Kim Nørgaard <jasen@jasen.dk>
data/Rakefile CHANGED
@@ -1,11 +1,3 @@
1
1
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
2
  require "rai/version"
3
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/TODO.md ADDED
@@ -0,0 +1,8 @@
1
+ # TODO
2
+ √ delete cookie if invalid
3
+ √ option to disable caching via parameter or route (nocache=1)
4
+ - maybe md5-sum for cache path (md5(request_path))
5
+ - transparent gift, transparent pngs
6
+ - check up on cookie-stuff - https://github.com/MattWilcox/Adaptive-Images/pull/139
7
+ - android pixel density - https://github.com/MattWilcox/Adaptive-Images/issues/99
8
+ - http client hints: https://github.com/MattWilcox/Adaptive-Images/pull/128
@@ -0,0 +1,7 @@
1
+ require 'rai'
2
+
3
+ map '/images' do
4
+ Rai::App.set :img_path, '/path/to/your/images'
5
+ Rai::App.set :cache_path, '/path/to/your/cache'
6
+ run Rai::App
7
+ end
data/lib/rai.rb CHANGED
@@ -1,146 +1,65 @@
1
- require 'sinatra'
1
+ require 'sinatra/base'
2
2
  require 'mini_magick'
3
3
  require 'fileutils'
4
4
 
5
+ require_relative 'rai/helpers'
6
+
5
7
  module Rai
6
8
  class App < Sinatra::Base
7
- # keep an eye on the cache to see if it needs updating
9
+ # Keep an eye on the cache to see if it needs updating
8
10
  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
11
+
12
+ # Resolution break-points (screen widths)
13
+ set :resolutions, [2560, 1920, 1440, 1024, 768, 480]
14
+
15
+ # JPG compression ratio, 0-100
16
+ set :jpg_quality, 85
17
+
18
+ # Sharpen images after resize
14
19
  set :sharpen, true
15
- # 7 days
20
+
21
+ # Cache Time-To-Live
16
22
  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
23
 
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
24
+ # Image location
25
+ set :img_path, File.join(File.dirname(__FILE__), '..', 'images')
27
26
 
28
- expires settings.cache_max_age, :private, :must_revalidate
27
+ # Cache location
28
+ set :cache_path, File.join(File.dirname(__FILE__), '..', 'images', 'rai-cache')
29
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
30
+ # Cookie name
31
+ set :cookie_name, 'rai-resolution'
37
32
 
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
33
+ # Supported image types
34
+ set :supported_image_types, ['jpg', 'jpeg', 'gif', 'png']
35
+
36
+ helpers Rai::Helpers
37
+
38
+ get %r{.*?(\.(?<image_type>[\w]+))?$} do
39
+ halt(406, "No image type/extension given") unless params[:image_type]
40
+ halt(406, "Unsupported image type: #{params[:image_type]}") unless settings.supported_image_types.include? params[:image_type]
41
+
42
+ @request_path = URI.decode(request.path_info)
43
+ @resolution = get_resolution
44
+ @requested_image = File.join(settings.img_path, @request_path)
45
+ not_found unless File.file? @requested_image
46
+ @cached_image = File.join(settings.cache_path, @resolution.to_s, @request_path)
47
+
48
+ # Just send the original image if the nocache parameter is set to 1
49
+ send_file @requested_image if params[:nocache] == '1'
50
+
51
+ # Generate image or use cached version
52
+ update_image
53
+
54
+ # Set caching headers
55
+ expires settings.cache_max_age, :private, :must_revalidate
56
+ last_modified File.mtime(@requested_image)
43
57
 
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
58
+ send_file @cached_image
140
59
  end
141
60
 
142
61
  not_found do
143
- "Not found: #{@request_path} not found."
62
+ "Not Found: #{request.path}"
144
63
  end
145
64
  end
146
65
  end
@@ -0,0 +1,101 @@
1
+ module Rai
2
+ module Helpers
3
+ def get_resolution
4
+ settings.resolutions.sort!{|x,y| y <=> x }
5
+ get_resolution_from_cookie || get_resolution_from_user_agent
6
+ end
7
+
8
+ def get_resolution_from_cookie
9
+ return false unless res_cookie = request.cookies[settings.cookie_name]
10
+
11
+ if res_cookie !~ /^[0-9]+[,]*[0-9\.]+$/
12
+ response.delete_cookie settings.cookie_name
13
+ else
14
+ cookie_data = res_cookie.split(',')
15
+ total_width = client_width = cookie_data[0].to_i
16
+ # the device's pixel density factor (physical pixels per CSS pixel)
17
+ pixel_density = cookie_data[1] ? cookie_data[1].to_i : 1
18
+ # by default use the largest supported break-point
19
+ resolution = settings.resolutions.first
20
+
21
+ total_width = client_width * pixel_density
22
+
23
+ resolution =
24
+ settings.resolutions.select {|res| total_width <= res}.last
25
+ resolution ||= settings.resolutions.first
26
+
27
+ if total_width > settings.resolutions.first
28
+ resolution *= pixel_density
29
+ end
30
+
31
+ return resolution
32
+ end
33
+ end
34
+
35
+ def get_resolution_from_user_agent
36
+ is_mobile ? settings.resolutions.min : settings.resolutions.max
37
+ end
38
+
39
+ def is_mobile
40
+ request.user_agent.downcase.match(/mobi|android|touch|mini/)
41
+ end
42
+
43
+ def update_image
44
+ # Refresh the image if the cached version is too old
45
+ if File.exists? @cached_image
46
+ return unless settings.watch_cache
47
+ return if File.mtime(@cached_image) >= File.mtime(@requested_image)
48
+ File.delete @cached_image
49
+ end
50
+
51
+ begin
52
+ image = MiniMagick::Image.open(@requested_image)
53
+ rescue Exception => e
54
+ halt(500, "Error loading image: #{e}")
55
+ end
56
+
57
+ # Do we need to downscale the image?
58
+ if image[:width] <= @resolution
59
+ @cached_image = @requested_image
60
+ return
61
+ end
62
+
63
+ cache_dir = File.dirname(@cached_image)
64
+
65
+ begin
66
+ FileUtils.mkdir_p(cache_dir, :mode => 0755) unless File.directory?(cache_dir)
67
+ rescue SystemCallError => e
68
+ halt(500, "Unable to create caching directory. #{e}")
69
+ rescue => e
70
+ halt(500, "Unable to create caching directory. #{e}")
71
+ end
72
+
73
+ ratio = image["%[fx:w/h]"].to_f
74
+ new_width = @resolution
75
+ new_height = (new_width*ratio).ceil
76
+
77
+ if params[:image_type] == 'jpg'
78
+ image.combine_options do |c|
79
+ c.interlace 'plane'
80
+ c.quality settings.jpg_quality
81
+ end
82
+ end
83
+
84
+ image.resize "#{new_width}x#{new_height}"
85
+
86
+ if settings.sharpen
87
+ radius = 0.5
88
+ sigma = 0.5
89
+ amount = 1.0
90
+ threshold = 0.02
91
+ image.unsharp "#{radius}x#{sigma}+#{amount}+#{threshold}"
92
+ end
93
+
94
+ begin
95
+ image.write @cached_image
96
+ rescue Exception => e
97
+ halt(500, "Error writing cache file: #{e}")
98
+ end
99
+ end
100
+ end
101
+ end
@@ -1,3 +1,3 @@
1
1
  module Rai
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kim Nørgaard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-24 00:00:00.000000000 Z
11
+ date: 2014-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -48,8 +48,10 @@ files:
48
48
  - Gemfile
49
49
  - README.md
50
50
  - Rakefile
51
- - config.ru
51
+ - TODO.md
52
+ - config.ru.sample
52
53
  - lib/rai.rb
54
+ - lib/rai/helpers.rb
53
55
  - lib/rai/version.rb
54
56
  - rai.gemspec
55
57
  homepage: https://github.com/KimNorgaard/rai
data/config.ru DELETED
@@ -1,4 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
- require 'rai'
3
-
4
- map('/photos') { run Rai::App }