Created
November 15, 2009 14:22
-
-
Save mbleigh/235251 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Rack | |
class Pictopus | |
def initialize(app, output_path) | |
@app = app | |
@root = ::File.expand_path(output_path) | |
raise ArgumentError, "#{output_path} is not a directory." unless ::File.directory?(@root) | |
end | |
def call(env) | |
unless env["PATH_INFO"] =~ /.*\/images\/pictopus\/.*\/.*/ | |
return @app.call(env) | |
end | |
request = ::Rack::Request.new(env) | |
kind, command = env["PATH_INFO"].match(/images\/pictopus\/(.*)\/(.*)/i)[1..-1] | |
if ::File.exist?(@root + env["PATH_INFO"]) | |
return ::Rack::File.new(@root).call(env) | |
end | |
case kind | |
when "gradient" | |
opts = { | |
:output_path => @root | |
} | |
opts[:start_color], opts[:end_color], opts[:orientation], opts[:size], opts[:format] = command.split('.') | |
::Pictopus::Gradient.new(opts).run! | |
# Redirect to this URL since it will now be served. | |
[301, {'Location' => request.url}, 'Redirecting to created image.'] | |
end | |
end | |
end | |
end | |
module Pictopus | |
class CommandLineError < StandardError; end | |
class << self | |
def default_options | |
@options ||= { | |
:command_path => nil, | |
:log => true, | |
:swallow_stderr => true, | |
:log_command => true | |
} | |
end | |
def run(cmd, params="", options = {}) | |
options[:expected_outcodes] ||= 0 | |
command = %Q[#{path_for_command(cmd)} #{params}].gsub(/\s+/, " ") | |
command = "#{command} 2>#{bit_bucket}" if Pictopus.default_options[:swallow_stderr] | |
#Rails.logger.info(command) if Pictopus.default_options[:log_command] | |
puts command | |
output = system(command) | |
unless Array(options[:expected_outcodes]).include?($?.exitstatus) | |
raise Pictopus::CommandLineError, "Error while running #{cmd}" | |
end | |
end | |
def path_for_command(command) | |
path = [default_options[:command_path], command].compact! | |
File.join(*path) | |
end | |
def bit_bucket #:nodoc: | |
File.exists?("/dev/null") ? "/dev/null" : "NUL" | |
end | |
end | |
end | |
module Pictopus | |
class Gradient | |
OPTION_KEYS = [:start_color, :end_color, :orientation, :size, :format] | |
# Provide some default options for | |
# generating gradients. You shouldn't | |
# ever really see this unless you're | |
# hacking on something custom. | |
def self.default_options | |
@options ||= { | |
:size => '100x100', | |
:format => 'png', | |
:orientation => 'vertical', | |
:start_color => 'fff', | |
:end_color => '000' | |
} | |
end | |
# Create a new Gradient object and provide | |
# options. The available options are enumerated | |
# in OPTION_KEYS. | |
def initialize(options = {}) | |
@options = self.class.default_options.merge(options) | |
end | |
# Convert this object to a string of command line arguments | |
# acceptable by ImageMagick. | |
def to_args | |
args = [] | |
args << "-size #{parse_size(size)}" | |
args << "gradient:#{parse_color(start_color)}-#{parse_color(end_color)}" | |
args << "-rotate -90" if horizontal? | |
args << File.join(output_directory, file_name) | |
args.join(' ') | |
end | |
# Run the actual command to generate the image | |
# for this instance. | |
def run! | |
FileUtils.mkdir_p(output_directory) unless File.directory?(File.dirname(output_directory)) | |
Pictopus.run('convert', self.to_args) | |
end | |
OPTION_KEYS.each do |opt| | |
class_eval <<-RUBY | |
def #{opt} | |
@options[#{opt.inspect}] | |
end | |
def #{opt}=(value) | |
@options[#{opt.inspect}] = value | |
end | |
RUBY | |
end | |
# True if the image is set to be a vertical gradient. | |
def vertical? | |
%w(v vertical).include?(orientation) | |
end | |
# True if the image is set to be a horizontal gradient. | |
def horizontal? | |
%w(h horizontal).include?(orientation) | |
end | |
def output_directory # :nodoc: | |
File.join(@options[:output_path], 'images', 'pictopus', 'gradient') | |
end | |
def file_name # :nodoc: | |
[start_color, end_color, orientation, size, format].join('.') | |
end | |
protected | |
def parse_color(color_string) | |
if color_string =~ /[0-9a-f]{3}/i || | |
color_string =~ /[0-9a-f]{6}/i || | |
color_string =~ /[0-9a-f]{8}/i | |
"##{color_string}".downcase | |
end | |
end | |
def parse_size(size_string) | |
dimensions = size_string.split('x') | |
case dimensions.size | |
when 2 | |
dimensions.reverse! if horizontal? | |
when 1 | |
dimensions.unshift('1') | |
end | |
dimensions.join('x') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment