Builds an info object (Prawn::Images::*) and a PDF reference representing the given image. Return a pair: [pdf_obj, info].
# File lib/prawn/images.rb, line 78 def build_image_object(file) # Rewind if the object we're passed is an IO, so that multiple embeds of # the same IO object will work file.rewind if file.respond_to?(:rewind) # read the file as binary so the size is calculated correctly file.binmode if file.respond_to?(:binmode) if file.respond_to?(:read) image_content = file.read else raise ArgumentError, "#{file} not found" unless File.file?(file) image_content = File.binread(file) end image_sha1 = Digest::SHA1.hexdigest(image_content) # if this image has already been embedded, just reuse it if image_registry[image_sha1] info = image_registry[image_sha1][:info] image_obj = image_registry[image_sha1][:obj] else # Build the image object klass = case Image.detect_image_format(image_content) when :jpg then Prawn::Images::JPG when :png then Prawn::Images::PNG end info = klass.new(image_content) # Bump PDF version if the image requires it min_version(info.min_pdf_version) if info.respond_to?(:min_pdf_version) # Add the image to the PDF and register it in case we see it again. image_obj = info.build_pdf_object(self) image_registry[image_sha1] = {:obj => image_obj, :info => info} end [image_obj, info] end
Given a PDF image resource pdf_obj
that has been added to the
page's resources and an info
object (the pair returned
from #build_image_object),
embed the image according to the options
given.
# File lib/prawn/images.rb, line 122 def embed_image(pdf_obj, info, options) # find where the image will be placed and how big it will be w,h = info.calc_image_dimensions(options) if options[:at] x,y = map_to_absolute(options[:at]) else x,y = image_position(w,h,options) move_text_position h end # add a reference to the image object to the current page # resource list and give it a label label = "I#{next_image_id}" state.page.xobjects.merge!(label => pdf_obj) # add the image to the current page instruct = "\nq\n%.3f 0 0 %.3f %.3f %.3f cm\n/%s Do\nQ" add_content instruct % [ w, h, x, y - h, label ] end
Add the image at filename to the current page. Currently only JPG and PNG files are supported.
NOTE: Prawn is very slow at rendering PNGs with alpha channels, and this uses a lot of RAM. The workaround for those who don't mind installing RMagick is to use:
github.com/amberbit/prawn-fast-png
Arguments:
file
path to file or an object that responds to read
Options:
:at
an array [x,y] with the location of the top left corner of the image.
:position
One of (:left, :center, :right) or an x-offset
:vposition
One of (:top, :center, :center) or an y-offset
:height
the height of the image [actual height of the image]
:width
the width of the image [actual width of the image]
:scale
scale the dimensions of the image proportionally
:fit
scale the dimensions of the image proportionally to fit inside [width,height]
Prawn::Document.generate("image2.pdf", :page_layout => :landscape) do pigs = "#{Prawn::DATADIR}/images/pigs.jpg" image pigs, :at => [50,450], :width => 450 dice = "#{Prawn::DATADIR}/images/dice.png" image dice, :at => [50, 450], :scale => 0.75 end
If only one of :width / :height are provided, the image will be scaled proportionally. When both are provided, the image will be stretched to fit the dimensions without maintaining the aspect ratio.
If :at is provided, the image will be place in the current page but the text position will not be changed.
If instead of an explicit filename, an object with a read method is passed
as file
, you can embed images from IO objects and things that
act like them (including Tempfiles and open-uri objects).
require "open-uri" Prawn::Document.generate("remote_images.pdf") do image open("http://prawn.majesticseacreature.com/media/prawn_logo.png") end
This method returns an image info object which can be used to check the dimensions of an image object if needed. (See also: Prawn::Images::PNG , Prawn::Images::JPG)
# File lib/prawn/images.rb, line 65 def image(file, options={}) Prawn.verify_options [:at, :position, :vposition, :height, :width, :scale, :fit], options pdf_obj, info = build_image_object(file) embed_image(pdf_obj, info, options) info end
# File lib/prawn/images.rb, line 175 def determine_y_with_page_flow(h) if overruns_page?(h) bounds.move_past_bottom end self.y end
# File lib/prawn/images.rb, line 145 def image_position(w,h,options) options[:position] ||= :left y = case options[:vposition] when :top bounds.absolute_top when :center bounds.absolute_top - (bounds.height - h) / 2.0 when :bottom bounds.absolute_bottom + h when Numeric bounds.absolute_top - options[:vposition] else determine_y_with_page_flow(h) end x = case options[:position] when :left bounds.left_side when :center bounds.left_side + (bounds.width - w) / 2.0 when :right bounds.right_side - w when Numeric options[:position] + bounds.left_side end return [x,y] end
# File lib/prawn/images.rb, line 186 def image_registry @image_registry ||= {} end
# File lib/prawn/images.rb, line 190 def next_image_id @image_counter ||= 0 @image_counter += 1 end
# File lib/prawn/images.rb, line 182 def overruns_page?(h) (self.y - h) < reference_bounds.absolute_bottom end