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 "" 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