Skip to content

Instantly share code, notes, and snippets.

@jcupitt
Forked from stanislaw/ruby-vips-vs-oil.rb
Created August 9, 2012 14:34
Show Gist options
  • Save jcupitt/3304701 to your computer and use it in GitHub Desktop.
Save jcupitt/3304701 to your computer and use it in GitHub Desktop.
Ruby-vips vs Oil
#!/usr/bin/env ruby
require 'rubygems'
gem 'ruby-vips'
gem 'oil'
require 'vips'
require 'oil'
require 'benchmark'
require 'stringio'
module Procedure
NUMBER = 1
IM_SIZE = 100
class << self
def run processor, img, best_of
result = nil
result = Benchmark.bmbm do |b|
(1 .. best_of).each do |number|
b.report number.to_s do
NUMBER.times do
send processor, img
end
end
end
end
output result
end
def output result
result = (result.map(&:to_a).map{|el| el[5]}.min * 1000).to_i
"#{result}ms"
end
class VipsProcessor
HIGH_QUALITY = false
SHARPEN_MASK = begin
conv_mask = [
[ -1, -1, -1 ],
[ -1, 24, -1 ],
[ -1, -1, -1 ]
]
::VIPS::Mask.new conv_mask, 16
end
attr_reader :src, :image
def initialize src
@src = src
resize_to_limit IM_SIZE, IM_SIZE
end
def resize_to_limit(new_width, new_height)
manipulate! do |image|
image = resize_image(image,new_width,new_height) if new_width < image.x_size || new_height < image.y_size
image
end
end
def manipulate!
@image ||= VIPS::Image.new(src)
@image = yield @image
rescue => e
raise("Failed to manipulate file, maybe it is not an image? Original Error: #{e}")
end
def resize_image(image, width, height, min_or_max = :min)
ratio = get_ratio image, width, height, min_or_max
if jpeg? # find the shrink ratio for loading
shrink_factor = [8, 4, 2, 1].find {|sf| 1.0 / ratio >= sf }
shrink_factor = 1 if shrink_factor == nil
image = VIPS::Image.jpeg src,
:shrink_factor => shrink_factor, :sequential => true
ratio = get_ratio image, width, height, min_or_max
elsif png?
image = VIPS::Image.png src, :sequential => true
end
if ratio > 1
image = image.affinei_resize :nearest, ratio
else
if HIGH_QUALITY
if ratio <= 0.5
factor = (1.0 / ratio).floor
puts "int shrink by factor = #{factor}"
image = image.shrink(factor)
image = image.tile_cache(image.x_size, 1, 10)
ratio = get_ratio image, width, height, min_or_max
end
image = image.affinei_resize :bilinear, ratio
image = image.conv SHARPEN_MASK
else
image = image.affinei_resize :nearest, ratio
end
end
image
end
def get_ratio(image, width,height, min_or_max = :min)
width_ratio = width.to_f / image.x_size
height_ratio = height.to_f / image.y_size
[width_ratio, height_ratio].send(min_or_max)
end
def jpeg?(path = src)
path =~ /.*jpg$/i or path =~ /.*jpeg$/i
end
def png?(path = src)
path =~ /.*png$/i
end
end
def vips_jpg src
processor = VipsProcessor.new(src)
output = processor.resize_to_limit IM_SIZE, IM_SIZE
output.jpeg("vips.#{src}")
end
def vips_png src
processor = VipsProcessor.new(src)
output = processor.resize_to_limit IM_SIZE, IM_SIZE
output.png("vips.#{src}")
end
def oil_jpg src
jpeg = Oil::JPEG.new(im(src), IM_SIZE, IM_SIZE)
File.open("oil.#{src}", 'wb') do |f|
jpeg.each { |data| f << data }
end
end
def oil_png src
png = Oil::PNG.new(im(src), IM_SIZE, IM_SIZE)
File.open("oil.#{src}", 'wb') do |f|
png.each { |data| f << data }
end
end
def im src
File.open src, 'rb'
end
end
end
best_of = 1
#result_vips_jpg = Procedure.run :vips_jpg, "peacock.jpg", best_of
result_vips_jpg = Procedure.run :vips_jpg, "wtc.jpg", best_of
result_vips_png = Procedure.run :vips_png, "peacock.png", best_of
#result_oil_jpg = Procedure.run :oil_jpg, "peacock.jpg", best_of
result_oil_jpg = Procedure.run :oil_jpg, "wtc.jpg", best_of
result_oil_png = Procedure.run :oil_png, "peacock.png", best_of
puts "Ruby-vips #{VIPS::VERSION} built against libvips #{VIPS::LIB_VERSION}"
print "ruby-vips, jpeg image: "
puts result_vips_jpg
print "ruby-vips, png image: "
puts result_vips_png
print "oil, jpeg image: "
puts result_oil_jpg
print "oil, png image: "
puts result_oil_png
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment