Class: Plugin::Thumbnailer::Service

Inherits:
Object
  • Object
show all
Extended by:
Stats
Includes:
ClassLogging
Defined in:
lib/httpthumbnailer/plugin/thumbnailer.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Service

Returns a new instance of Service.



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 232

def initialize(options = {})
  @processing_methods = {}
  @options = options
  @images_loaded = 0

  log.info "initializing thumbnailer: #{self.class.rmagick_version} #{self.class.magick_version}"

  set_limit(:area, options[:limit_area]) if options.member?(:limit_area)
  set_limit(:memory, options[:limit_memory]) if options.member?(:limit_memory)
  set_limit(:map, options[:limit_map]) if options.member?(:limit_map)
  set_limit(:disk, options[:limit_disk]) if options.member?(:limit_disk)

  Magick.trace_proc = lambda do |which, description, id, method|
    case which
    when :c
      Service.stats.incr_images_loaded
      @images_loaded += 1
      Service.stats.max_images_loaded = Service.stats.images_loaded if Service.stats.images_loaded > Service.stats.max_images_loaded
      Service.stats.max_images_loaded_worker = @images_loaded if @images_loaded > Service.stats.max_images_loaded_worker
      Service.stats.incr_total_images_created
      case method
      when :from_blob
        Service.stats.incr_total_images_created_from_blob
      when :initialize
        Service.stats.incr_total_images_created_initialize
      when :resize
        Service.stats.incr_total_images_created_resize
      when :resize!
        Service.stats.incr_total_images_created_resize
      when :crop
        Service.stats.incr_total_images_created_crop
      when :crop!
        Service.stats.incr_total_images_created_crop
      when :sample
        Service.stats.incr_total_images_created_sample
      else
        log.warn "uncounted image creation method: #{method}"
      end
    when :d
      Service.stats.decr_images_loaded
      @images_loaded -= 1
      Service.stats.incr_total_images_destroyed
    end
    log.debug{"image event: #{which}, #{description}, #{id}, #{method}: loaded images: #{Service.stats.images_loaded}"}
  end
end

Class Method Details

.input_formatsObject



212
213
214
215
216
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 212

def self.input_formats
  Magick.formats.select do |name, mode|
    mode.include? 'r'
  end.keys.map(&:downcase)
end

.magick_versionObject



228
229
230
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 228

def self.magick_version
  Magick::Magick_version
end

.output_formatsObject



218
219
220
221
222
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 218

def self.output_formats
  Magick.formats.select do |name, mode|
    mode.include? 'w'
  end.keys.map(&:downcase)
end

.rmagick_versionObject



224
225
226
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 224

def self.rmagick_version
  Magick::Version
end

Instance Method Details

#load(io, options = {}) ⇒ Object



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 279

def load(io, options = {})
  mw = options[:max_width]
  mh = options[:max_height]
  if mw and mh
    mw = mw.to_i
    mh = mh.to_i
    log.info "using max size hint of: #{mw}x#{mh}"
  end

  begin
    blob = io.read

    old_memory_limit = nil
    borrowed_memory_limit = nil
    if options.member?(:limit_memory)
      borrowed_memory_limit = options[:limit_memory].borrow(options[:limit_memory].limit, 'image magick')
      old_memory_limit = set_limit(:memory, borrowed_memory_limit)
    end

    images = Magick::Image.from_blob(blob) do |info|
      if mw and mh
        define('jpeg', 'size', "#{mw*2}x#{mh*2}")
        define('jbig', 'size', "#{mw*2}x#{mh*2}")
      end
    end

    image = images.first
    if image.columns > image.base_columns or image.rows > image.base_rows and not options[:no_reload]
      log.warn "input image got upscaled from: #{image.base_columns}x#{image.base_rows} to #{image.columns}x#{image.rows}: reloading without max size hint!"
      images.each do |other|
        other.destroy!
      end
      images = Magick::Image.from_blob(blob)
      Service.stats.incr_total_images_reloaded
    end
    blob = nil

    images.shift.replace do |image|
      images.each do |other|
        other.destroy!
      end
      log.info "loaded image: #{image.inspect}"
      Service.stats.incr_total_images_loaded

      # clean up the image
      image.strip!
      image.properties do |key, value|
        log.debug "deleting user propertie '#{key}'"
        image[key] = nil
      end

      image
    end.replace do |image|
      if mw and mh and not options[:no_downscale]
        f = image.find_downscale_factor(mw, mh)
        if f > 1
          image = image.downscale(f)
          log.info "downscaled image by factor of #{f}: #{image.inspect}"
          Service.stats.incr_total_images_downscaled
        end
      end
      InputImage.new(image, @processing_methods)
    end
  rescue Magick::ImageMagickError => error
    raise ImageTooLargeError, error if error.message =~ /cache resources exhausted/
    raise UnsupportedMediaTypeError, error
  ensure
    if old_memory_limit
      set_limit(:memory, old_memory_limit)
      options[:limit_memory].return(borrowed_memory_limit, 'image magick')
    end
  end
end

#processing_method(method, &impl) ⇒ Object



353
354
355
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 353

def processing_method(method, &impl)
  @processing_methods[method] = impl
end

#set_limit(limit, value) ⇒ Object



357
358
359
360
361
# File 'lib/httpthumbnailer/plugin/thumbnailer.rb', line 357

def set_limit(limit, value)
  old = Magick.limit_resource(limit, value)
  log.info "changed #{limit} limit from #{old} to #{value} bytes"
  old
end