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.