class ImageOptim

Main interface

Attributes

allow_lossy[R]

Allow lossy workers and optimizations

cache_dir[R]

Cache directory

cache_worker_digests[R]

Cache worker digests

nice[R]

Nice level

pack[R]

Use image_optim_pack

skip_missing_workers[R]

Skip workers with missing or problematic binaries

threads[R]

Number of threads to run with

timeout[R]

Timeout

verbose[R]

Verbose output?

Public Class Methods

full_version() click to toggle source

Full version of image_optim

# File lib/image_optim.rb, line 216
def full_version
  "image_optim v#{version}"
end
method_missing(method, *args, &block) click to toggle source

Optimization methods with default options

Calls superclass method
# File lib/image_optim.rb, line 190
def method_missing(method, *args, &block)
  if optimize_image_method?(method)
    new.send(method, *args, &block)
  else
    super
  end
end
new(options = {}) click to toggle source

Initialize workers, specify options using worker underscored name:

pass false to disable worker

ImageOptim.new(:pngcrush => false)

or hash with options to worker

ImageOptim.new(:advpng => {:level => 3}, :optipng => {:level => 2})

use :threads to set number of parallel optimizers to run (passing true or nil determines number of processors, false disables parallel processing)

ImageOptim.new(:threads => 8)

use :nice to specify optimizers nice level (true or nil makes it 10, false makes it 0)

ImageOptim.new(:nice => 20)
# File lib/image_optim.rb, line 71
def initialize(options = {})
  config = Config.new(options)
  @verbose = config.verbose
  $stderr << "config:\n#{config.to_s.gsub(/^/, '  ')}" if verbose

  %w[
    nice
    threads
    pack
    skip_missing_workers
    allow_lossy
    cache_dir
    cache_worker_digests
    timeout
  ].each do |name|
    instance_variable_set(:"@#{name}", config.send(name))
    $stderr << "#{name}: #{send(name)}\n" if verbose
  end

  @bin_resolver = BinResolver.new(self)

  @workers_by_format = Worker.create_all_by_format(self) do |klass|
    config.for_worker(klass)
  end

  @cache = Cache.new(self, @workers_by_format)

  log_workers_by_format if verbose

  config.assert_no_unused_options!
end
respond_to?(method, include_private = false) click to toggle source
Calls superclass method
# File lib/image_optim.rb, line 203
def respond_to?(method, include_private = false)
  optimize_image_method?(method) || super
end
respond_to_missing?(method, include_private = false) click to toggle source
Calls superclass method
# File lib/image_optim.rb, line 198
def respond_to_missing?(method, include_private = false)
  optimize_image_method?(method) || super
end
version() click to toggle source

Version of image_optim gem spec loaded

# File lib/image_optim.rb, line 209
def version
  Gem.loaded_specs['image_optim'].version.to_s
rescue
  'DEV'
end

Private Class Methods

optimize_image_method?(method) click to toggle source
# File lib/image_optim.rb, line 222
def optimize_image_method?(method)
  method_defined?(method) && method.to_s =~ /^optimize_image/
end

Public Instance Methods

env_path() click to toggle source

Join resolve_dir, default path and vendor path for PATH environment variable

# File lib/image_optim.rb, line 239
def env_path
  @bin_resolver.env_path
end
optimizable?(path) click to toggle source

Are there workers for file at path?

# File lib/image_optim.rb, line 228
def optimizable?(path)
  !!workers_for_image(path)
end
optimize_image(original) click to toggle source

Optimize one file, return new path as OptimizedPath or nil if optimization failed

# File lib/image_optim.rb, line 110
def optimize_image(original)
  original = Path.convert(original)
  return unless (workers = workers_for_image(original))

  optimized = @cache.fetch(original) do
    Handler.for(original) do |handler|
      current_worker = nil

      begin
        with_timeout(@timeout) do
          workers.each do |worker|
            current_worker = worker
            handler.process{ |src, dst| worker.optimize(src, dst) }
          end
        end
      rescue TimeoutExceeded => e
        if current_worker && current_worker.pid
          pid = current_worker.pid
          cleanup_process(pid)
        end

        raise e
      end
    end
  end

  return unless optimized
  OptimizedPath.new(optimized, original)
end
optimize_image!(original) click to toggle source

Optimize one file in place, return original as OptimizedPath or nil if optimization failed

# File lib/image_optim.rb, line 142
def optimize_image!(original)
  original = Path.convert(original)
  return unless (result = optimize_image(original))
  result.replace(original)
  OptimizedPath.new(original, result.original_size)
end
optimize_image_data(original_data) click to toggle source

Optimize image data, return new data or nil if optimization failed

# File lib/image_optim.rb, line 150
def optimize_image_data(original_data)
  format = ImageMeta.format_for_data(original_data)
  return unless format
  Path.temp_file %W[image_optim .#{format}] do |temp|
    temp.binmode
    temp.write(original_data)
    temp.close

    if (result = optimize_image(temp.path))
      result.binread
    end
  end
end
optimize_images(paths, &block) click to toggle source

Optimize multiple images if block given yields path and result for each image and returns array of yield results else return array of path and result pairs

# File lib/image_optim.rb, line 168
def optimize_images(paths, &block)
  run_method_for(paths, :optimize_image, &block)
end
optimize_images!(paths, &block) click to toggle source

Optimize multiple images in place if block given yields path and result for each image and returns array of yield results else return array of path and result pairs

# File lib/image_optim.rb, line 176
def optimize_images!(paths, &block)
  run_method_for(paths, :optimize_image!, &block)
end
optimize_images_data(datas, &block) click to toggle source

Optimize multiple image datas if block given yields original and result for each image data and returns array of yield results else return array of path and result pairs

# File lib/image_optim.rb, line 184
def optimize_images_data(datas, &block)
  run_method_for(datas, :optimize_image_data, &block)
end
resolve_bin!(bin) click to toggle source

Check existance of binary, create symlink if ENV contains path for key XXX_BIN where XXX is upper case bin name

# File lib/image_optim.rb, line 234
def resolve_bin!(bin)
  @bin_resolver.resolve!(bin)
end
workers_for_image(path) click to toggle source

Get workers for image

# File lib/image_optim.rb, line 104
def workers_for_image(path)
  @workers_by_format[Path.convert(path).image_format]
end

Private Instance Methods

apply_threading(enum) click to toggle source

Apply threading if threading is allowed

# File lib/image_optim.rb, line 305
def apply_threading(enum)
  if threads > 1
    enum.in_threads(threads)
  else
    enum
  end
end
cleanup_process(pid) click to toggle source
# File lib/image_optim.rb, line 257
def cleanup_process(pid)
  Process.detach(pid)
  Process.kill('-TERM', pid)
  now = Time.now

  while Time.now - now < 10
    begin
      Process.getpgid(pid)
      sleep 0.1
    rescue Errno::ESRCH
      break
    end
  end

  Process.kill('-KILL', pid) if Process.getpgid(pid)
rescue Errno::ESRCH
  pid
end
log_workers_by_format() click to toggle source
# File lib/image_optim.rb, line 276
def log_workers_by_format
  $stderr << "Workers by format:\n"
  @workers_by_format.each do |format, workers|
    $stderr << "#{format}:\n"
    workers.each do |worker|
      $stderr << "  #{worker.class.bin_sym}:\n"
      worker.options.each do |name, value|
        $stderr << "    #{name}: #{value.inspect}\n"
      end
    end
  end
end
run_method_for(list, method_name) { |item, result| ... } click to toggle source

Run method for each item in list if block given yields item and result for item and returns array of yield results else return array of item and result pairs

# File lib/image_optim.rb, line 293
def run_method_for(list, method_name, &block)
  apply_threading(list).map do |item|
    result = send(method_name, item)
    if block
      yield item, result
    else
      [item, result]
    end
  end
end
with_timeout(timeout) { || ... } click to toggle source
# File lib/image_optim.rb, line 245
def with_timeout(timeout)
  if timeout && timeout >= 0
    thread = Thread.new{ yield if block_given? }
    if thread.respond_to?(:report_on_exception)
      thread.report_on_exception = false
    end
    fail TimeoutExceeded if thread.join(timeout).nil?
  elsif block_given?
    yield
  end
end