rai 0.0.2 → 0.0.3

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 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 }