module Prawn::Images
Public Instance Methods
Builds an info object (Prawn::Images::*) and a PDF reference representing the given image. Return a pair: [pdf_obj, info].
@private
# File lib/prawn/images.rb, line 76 def build_image_object(file) io = verify_and_open_image(file) image_content = io.read 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 info = Prawn.image_handler.find(image_content).new(image_content) # Bump PDF version if the image requires it renderer.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.
@private
# File lib/prawn/images.rb, line 106 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) cm_params = PDF::Core.real_params([ w, 0, 0, h, x, y - h]) renderer.add_content("\nq\n#{cm_params} cm\n/#{label} Do\nQ") end
Add the image at filename to the current page. Currently only JPG and PNG files are supported. (Note that processing PNG images with alpha channels can be processor and memory intensive.)
Arguments:
file
-
path to file or an object that responds to read and rewind
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 62 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
Private Instance Methods
# File lib/prawn/images.rb, line 177 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 147 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 188 def image_registry @image_registry ||= {} end
# File lib/prawn/images.rb, line 192 def next_image_id @image_counter ||= 0 @image_counter += 1 end
# File lib/prawn/images.rb, line 184 def overruns_page?(h) (self.y - h) < reference_bounds.absolute_bottom end
# File lib/prawn/images.rb, line 128 def verify_and_open_image(io_or_path) # File or IO if io_or_path.respond_to?(:rewind) io = io_or_path # Rewind if the object we're passed is an IO, so that multiple embeds of # the same IO object will work io.rewind # read the file as binary so the size is calculated correctly # guard binmode because some objects acting io-like don't implement it io.binmode if io.respond_to?(:binmode) return io end # String or Pathname io_or_path = Pathname.new(io_or_path) fail ArgumentError, "#{io_or_path} not found" unless io_or_path.file? io = io_or_path.open('rb') io end