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. 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 # |
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::BASEDIR}/data/images/pigs.jpg" image pigs, :at => [50,450], :width => 450 dice = "#{Prawn::BASEDIR}/data/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 65: def image(file, options={}) 66: Prawn.verify_options [:at, :position, :vposition, :height, 67: :width, :scale, :fit], options 68: 69: if file.respond_to?(:read) 70: image_content = file.read 71: else 72: raise ArgumentError, "#{file} not found" unless File.file?(file) 73: image_content = File.binread(file) 74: end 75: 76: image_sha1 = Digest::SHA1.hexdigest(image_content) 77: 78: # if this image has already been embedded, just reuse it 79: if image_registry[image_sha1] 80: info = image_registry[image_sha1][:info] 81: image_obj = image_registry[image_sha1][:obj] 82: else 83: # Build the image object 84: klass = case detect_image_format(image_content) 85: when :jpg then Prawn::Images::JPG 86: when :png then Prawn::Images::PNG 87: end 88: info = klass.new(image_content) 89: 90: # Bump PDF version if the image requires it 91: min_version(info.min_pdf_version) if info.respond_to?(:min_pdf_version) 92: 93: # Add the image to the PDF and register it in case we see it again. 94: image_obj = info.build_pdf_object(self) 95: image_registry[image_sha1] = {:obj => image_obj, :info => info} 96: end 97: 98: # find where the image will be placed and how big it will be 99: w,h = calc_image_dimensions(info, options) 100: 101: if options[:at] 102: x,y = map_to_absolute(options[:at]) 103: else 104: x,y = image_position(w,h,options) 105: move_text_position h 106: end 107: 108: # add a reference to the image object to the current page 109: # resource list and give it a label 110: label = "I#{next_image_id}" 111: state.page.xobjects.merge!( label => image_obj ) 112: 113: # add the image to the current page 114: instruct = "\nq\n%.3f 0 0 %.3f %.3f %.3f cm\n/%s Do\nQ" 115: add_content instruct % [ w, h, x, y - h, label ] 116: 117: return info 118: end
# File lib/prawn/images.rb, line 164 164: def calc_image_dimensions(info, options) 165: w = options[:width] || info.width 166: h = options[:height] || info.height 167: 168: if options[:width] && !options[:height] 169: wp = w / info.width.to_f 170: w = info.width * wp 171: h = info.height * wp 172: elsif options[:height] && !options[:width] 173: hp = h / info.height.to_f 174: w = info.width * hp 175: h = info.height * hp 176: elsif options[:scale] 177: w = info.width * options[:scale] 178: h = info.height * options[:scale] 179: elsif options[:fit] 180: bw, bh = options[:fit] 181: bp = bw / bh.to_f 182: ip = info.width / info.height.to_f 183: if ip > bp 184: w = bw 185: h = bw / ip 186: else 187: h = bh 188: w = bh * ip 189: end 190: end 191: info.scaled_width = w 192: info.scaled_height = h 193: [w,h] 194: end
# File lib/prawn/images.rb, line 196 196: def detect_image_format(content) 197: top = content[0,128] 198: 199: # Unpack before comparing for JPG header, so as to avoid having to worry 200: # about the source string encoding. We just want a byte-by-byte compare. 201: if top[0, 3].unpack("C*") == [255, 216, 255] 202: return :jpg 203: elsif top[0, 8].unpack("C*") == [137, 80, 78, 71, 13, 10, 26, 10] 204: return :png 205: else 206: raise Errors::UnsupportedImageType, "image file is an unrecognised format" 207: end 208: end
# File lib/prawn/images.rb, line 151 151: def determine_y_with_page_flow(h) 152: if overruns_page?(h) 153: start_new_page 154: bounds.absolute_top 155: else 156: self.y 157: end 158: end
# File lib/prawn/images.rb, line 122 122: def image_position(w,h,options) 123: options[:position] ||= :left 124: 125: x = case options[:position] 126: when :left 127: bounds.absolute_left 128: when :center 129: bounds.absolute_left + (bounds.width - w) / 2.0 130: when :right 131: bounds.absolute_right - w 132: when Numeric 133: options[:position] + bounds.absolute_left 134: end 135: 136: y = case options[:vposition] 137: when :top 138: bounds.absolute_top 139: when :center 140: bounds.absolute_top - (bounds.height - h) / 2.0 141: when :bottom 142: bounds.absolute_bottom + h 143: when Numeric 144: bounds.absolute_top - options[:vposition] 145: else 146: determine_y_with_page_flow(h) 147: end 148: return [x,y] 149: end
# File lib/prawn/images.rb, line 210 210: def image_registry 211: @image_registry ||= {} 212: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.