Website/lib/image.rb

83 lines
2.3 KiB
Ruby

require "base64"
require "tempfile"
require "open-uri"
module ImageSmith
def ImageSmith::img(source, params = {})
puts "Render #{source}"
temp_file = nil
if source.start_with?("http") then
temp_file = Tempfile.new("img")
open(source) do |f|
temp_file.write(f.read)
end
temp_file.flush
puts "Downloading to #{temp_file.path}"
source = temp_file.path
end
padding = { left: 0, right: 0, top: 0, bottom: 0 }
metadata = identify(source)
size = metadata[:size].clone
conversion_params = []
uri = source
if params.has_key? :bounding_box
box = params[:bounding_box]
scale = size.zip(params[:bounding_box])
.map { |base, target| target.to_f / base.to_f }
.min
size.map!{ |dim| (dim * scale).to_i }
conversion_params = ["-resize", box.join("x")]
errors = box.zip(size).map { |target, actual| target - actual }
padding[:left] += errors[0]/2
padding[:right] += errors[0]/2
padding[:top] += errors[1]/2
padding[:bottom] += errors[1]/2
end
if params.fetch(:inline, false)
# fmt = case metadata[:format]
# when :JPEG then "image/jpeg"
# when :GIF then "image/gif"
# when :PNG then "image/png"
# else raise "Unknown format #{metadata[:format]}"
# end
fmt = "image/png"
data = IO.popen(["convert", source]+conversion_params+["-strip", "png:-"]) do |c|
Base64.encode64(c.read)
end
uri = "data:#{fmt};base64,#{data}"
p uri.length
end
style = {
padding: [:top, :right, :bottom, :left].map { |dir| padding[dir].to_s+"px" }.join(" ")
}
fields = {
src: uri,
width: size[0] + padding[:left] + padding[:right],
height: size[1] + padding[:top] + padding[:bottom],
style: style.map { |k, v| "#{k}:#{v}" }.join(';')
}
return "<img #{fields.map { |k, v| "#{k}=\"#{v}\"" }.join(" ") } />"
end
def ImageSmith::identify(path)
IO.popen(["identify", path]) do |i|
raw = i.read.chomp.split(/ +/)
metadata = {
path: raw[0],
format: raw[1].to_sym,
size: raw[2].split(/x/).map { |x| x.to_i },
raw: raw
}
return metadata
end
end
end