class Thumbor::CryptoURL

Public Class Methods

new(key = nil) click to toggle source
   # File lib/thumbor/crypto_url.rb
10 def initialize(key = nil)
11   @key = key
12 end

Public Instance Methods

calculate_centered_crop(options) click to toggle source
    # File lib/thumbor/crypto_url.rb
 40 def calculate_centered_crop(options)
 41   width = options[:width]
 42   height = options[:height]
 43   original_width = options[:original_width]
 44   original_height = options[:original_height]
 45   center = options[:center]
 46 
 47   return unless original_width &&
 48                 original_height &&
 49                 center &&
 50                 (width || height)
 51 
 52   raise 'center must be an array of x,y' unless center.is_a?(Array) && center.length == 2
 53 
 54   center_x, center_y = center
 55   width ||= original_width
 56   height ||= original_height
 57   width = width.abs
 58   height = height.abs
 59   new_aspect_ratio = width / height.to_f
 60   original_aspect_ratio = original_width / original_height.to_f
 61 
 62   crop = nil
 63   # We're going wider, vertical crop
 64   if new_aspect_ratio > original_aspect_ratio
 65     # How tall should we be? because new_aspect_ratio is > original_aspect_ratio we can be sure
 66     # that cropped_height is always less than original_height (original). This is assumed below.
 67     cropped_height = (original_width / new_aspect_ratio).round
 68     # Calculate coordinates around center
 69     top_crop_point = (center_y - (cropped_height * 0.5)).round
 70     bottom_crop_point = (center_y + (cropped_height * 0.5)).round
 71 
 72     # If we've gone above the top of the image, take all from the bottom
 73     if top_crop_point.negative?
 74       top_crop_point = 0
 75       bottom_crop_point = cropped_height
 76     # If we've gone below the top of the image, take all from the top
 77     elsif bottom_crop_point > original_height
 78       top_crop_point = original_height - cropped_height
 79       bottom_crop_point = original_height
 80       # Because cropped_height < original_height, top_crop_point and
 81       # bottom_crop_point will never both be out of bounds
 82     end
 83 
 84     # Put it together
 85     crop = [0, top_crop_point, original_width, bottom_crop_point]
 86   # We're going taller, horizontal crop
 87   elsif new_aspect_ratio < original_aspect_ratio
 88     # How wide should we be? because new_aspect_ratio is < original_aspect_ratio we can be sure
 89     # that cropped_width is always less than original_width (original). This is assumed below.
 90     cropped_width = (original_height * new_aspect_ratio).round
 91     # Calculate coordinates around center
 92     left_crop_point = (center_x - (cropped_width * 0.5)).round
 93     right_crop_point = (center_x + (cropped_width * 0.5)).round
 94 
 95     # If we've gone beyond the left of the image, take all from the right
 96     if left_crop_point.negative?
 97       left_crop_point = 0
 98       right_crop_point = cropped_width
 99     # If we've gone beyond the right of the image, take all from the left
100     elsif right_crop_point > original_width
101       left_crop_point = original_width - cropped_width
102       right_crop_point = original_width
103       # Because cropped_width < original_width, left_crop_point and
104       # right_crop_point will never both be out of bounds
105     end
106 
107     # Put it together
108     crop = [left_crop_point, 0, right_crop_point, original_height]
109   end
110 
111   options[:crop] = crop
112 end
calculate_width_and_height(url_parts, options) click to toggle source
   # File lib/thumbor/crypto_url.rb
14 def calculate_width_and_height(url_parts, options)
15   width = options[:width]
16   height = options[:height]
17 
18   width *= -1 if width && options[:flip]
19   height *= -1 if height && options[:flop]
20 
21   if width || height
22     width ||= 0
23     height ||= 0
24   end
25 
26   has_width = width
27   has_height = height
28   if options[:flip] && !has_width && !has_height
29     width = '-0'
30     height = '0' if !has_height && !(options[:flop])
31   end
32   if options[:flop] && !has_width && !has_height
33     height = '-0'
34     width = '0' if !has_width && !(options[:flip])
35   end
36 
37   url_parts.push("#{width}x#{height}") if width || height
38 end
generate(options) click to toggle source
    # File lib/thumbor/crypto_url.rb
175 def generate(options)
176   thumbor_path = []
177 
178   image_options = url_for(options)
179   thumbor_path << "#{image_options}/" unless image_options.empty?
180 
181   thumbor_path << options[:image]
182 
183   if @key.nil?
184     thumbor_path.insert(0, '/unsafe/')
185   else
186     signature = url_safe_base64(OpenSSL::HMAC.digest('sha1', @key, thumbor_path.join))
187     thumbor_path.insert(0, "/#{signature}/")
188   end
189   thumbor_path.join
190 end
url_for(options) click to toggle source
    # File lib/thumbor/crypto_url.rb
114 def url_for(options)
115   raise 'image is a required argument.' unless options[:image]
116 
117   url_parts = []
118 
119   url_parts.push('debug') if options[:debug]
120 
121   if options[:trim]
122     trim_options = ['trim']
123     trim_options << options[:trim] unless (options[:trim] == true) || (options[:trim][0] == true)
124     url_parts.push(trim_options.join(':'))
125   end
126 
127   url_parts.push('meta') if options[:meta]
128 
129   calculate_centered_crop(options)
130 
131   crop = options[:crop]
132   if crop
133     crop_left = crop[0]
134     crop_top = crop[1]
135     crop_right = crop[2]
136     crop_bottom = crop[3]
137 
138     if crop_left.positive? || crop_top.positive? || crop_bottom.positive? || crop_right.positive?
139       url_parts.push(crop_left.to_s << 'x' << crop_top.to_s << ':' << crop_right.to_s << 'x' << crop_bottom.to_s)
140     end
141   end
142 
143   %i[fit_in adaptive_fit_in full_fit_in adaptive_full_fit_in].each do |fit|
144     url_parts.push(fit.to_s.gsub('_', '-')) if options[fit]
145   end
146 
147   if (options.include?(:fit_in) || options.include?(:full_fit_in)) && !(options.include?(:width) || options.include?(:height))
148     raise ArgumentError, 'When using fit-in or full-fit-in, you must specify width and/or height.'
149   end
150 
151   calculate_width_and_height(url_parts, options)
152 
153   url_parts.push(options[:halign]) if options[:halign] && (options[:halign] != :center)
154 
155   url_parts.push(options[:valign]) if options[:valign] && (options[:valign] != :middle)
156 
157   url_parts.push('smart') if options[:smart]
158 
159   if options[:filters] && !options[:filters].empty?
160     filter_parts = []
161     options[:filters].each do |filter|
162       filter_parts.push(filter)
163     end
164 
165     url_parts.push("filters:#{filter_parts.join(':')}")
166   end
167 
168   url_parts.join('/')
169 end
url_safe_base64(str) click to toggle source
    # File lib/thumbor/crypto_url.rb
171 def url_safe_base64(str)
172   Base64.encode64(str).gsub('+', '-').gsub('/', '_').gsub!(/\n/, '')
173 end