module Fleximage module Operator # Draw text on the image. Customize size, position, color, dropshadow, and font. # # image.text(string_to_write, options = {}) # # Use the following keys in the +options+ hash: # # * alignment: symbol like in ImageOverlay # * offset: size string # * antialias: true or false # * color: string or color(r, g, b) # * font_size: integer # * font: path to a font file relative to +Rails.root+ # * rotate: degrees as an integer # * shadow: {:blur => 1, :opacity => 1.0} # * font_weight: RMagick font weight constant or value. See: http://www.imagemagick.org/RMagick/doc/draw.html#font_weight # * stroke: hash that, if present, will stroke the text. The hash should have both :width (integer) and :color (string or color object). # # Example: # # @photo.operate do |image| # image.text('I like Cheese', # :alignment => :top_left, # :offset => '300x150', # :antialias => true, # :color => 'pink', # :font_size => 24, # :font => 'path/to/myfont.ttf', # :rotate => -15, # :shadow => { # :blur => 1, # :opacity => 0.5, # }, # :stroke => { # :width => 3, # :color => color(0, 0, 0), # } # ) # end class Text < Operator::Base def operate(string_to_write, options = {}) options = { :alignment => :top_left, :offset => '0x0', :antialias => true, :color => 'black', :font_size => '12', :font => nil, :text_align => :left, :rotate => 0, :shadow => nil, :stroke => { :width => 0, :color => 'white', } }.merge(options) options[:offset] = size_to_xy(options[:offset]) # prepare drawing surface text = Magick::Draw.new text.gravity = symbol_to_gravity(options[:alignment]) text.fill = options[:color] text.text_antialias = options[:antialias] text.pointsize = options[:font_size].to_i text.rotation = options[:rotate] text.font_weight = options[:font_weight] if options[:font_weight] if options[:stroke][:width] > 0 text.stroke_width = options[:stroke][:width] text.stroke = options[:stroke][:color] end # assign font path with to rails root unless the path is absolute if options[:font] font = options[:font] font = "#{Rails.root}/#{font}" unless font =~ %r{^(~?|[A-Za-z]:)/} text.font = font end # draw text on transparent image temp_image = Magick::Image.new(@image.columns, @image.rows) { self.background_color = 'none' } temp_image = temp_image.annotate(text, 0, 0, options[:offset][0], options[:offset][1], string_to_write) # add drop shadow to text image if options[:shadow] shadow_args = [2, 2, 1, 1] if options[:shadow].is_a?(Hash) #shadow_args[0], shadow_args[1] = size_to_xy(options[:shadow][:offset]) if options[:shadow][:offset] shadow_args[2] = options[:shadow][:blur] if options[:shadow][:blur] shadow_args[3] = options[:shadow][:opacity] if options[:shadow][:opacity] end shadow = temp_image.shadow(*shadow_args) temp_image = shadow.composite(temp_image, 0, 0, symbol_to_blending_mode(:over)) end # composite text on original image @image.composite!(temp_image, 0, 0, symbol_to_blending_mode(:over)) end end end end