lib/prawn/images/png.rb in prawn-1.0.0.rc1 vs lib/prawn/images/png.rb in prawn-1.0.0.rc2
- old
+ new
@@ -167,11 +167,10 @@
:Type => :XObject,
:Subtype => :Image,
:Height => height,
:Width => width,
:BitsPerComponent => bits,
- :Length => img_data.size,
:Filter => :FlateDecode
)
unless alpha_channel
obj.data[:DecodeParms] = {:Predictor => 15,
@@ -180,21 +179,21 @@
:Columns => width}
end
# append the actual image data to the object as a stream
obj << img_data
-
+
# sort out the colours of the image
if palette.empty?
obj.data[:ColorSpace] = color
else
# embed the colour palette in the PDF as a object stream
- palette_obj = document.ref!(:Length => palette.size)
+ palette_obj = document.ref!({})
palette_obj << palette
# build the color space array for the image
- obj.data[:ColorSpace] = [:Indexed,
+ obj.data[:ColorSpace] = [:Indexed,
:DeviceRGB,
(palette.size / 3) -1,
palette_obj]
end
@@ -232,11 +231,10 @@
:Type => :XObject,
:Subtype => :Image,
:Height => height,
:Width => width,
:BitsPerComponent => alpha_channel_bits,
- :Length => alpha_channel.size,
:Filter => :FlateDecode,
:ColorSpace => :DeviceGray,
:Decode => [0, 1]
)
smask_obj << alpha_channel
@@ -260,21 +258,28 @@
end
private
def unfilter_image_data
- data = Zlib::Inflate.inflate(@img_data).unpack 'C*'
+ data = Zlib::Inflate.inflate(@img_data).bytes
@img_data = ""
@alpha_channel = ""
pixel_bytes = pixel_bitlength / 8
scanline_length = pixel_bytes * self.width + 1
row = 0
pixels = []
+ row_data = [] # reused for each row of the image
paeth, pa, pb, pc = nil
- until data.empty? do
- row_data = data.slice! 0, scanline_length
+
+ data.each do |byte|
+ # accumulate a whole scanline of bytes, and then process it all at once
+ # we could do this with Enumerable#each_slice, but it allocates memory,
+ # and we are trying to avoid that
+ row_data << byte
+ next if row_data.length < scanline_length
+
filter = row_data.shift
case filter
when 0 # None
when 1 # Sub
row_data.each_with_index do |byte, index|
@@ -282,26 +287,26 @@
row_data[index] = (byte + left) % 256
#p [byte, left, row_data[index]]
end
when 2 # Up
row_data.each_with_index do |byte, index|
- col = index / pixel_bytes
+ col = (index / pixel_bytes).floor
upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
row_data[index] = (upper + byte) % 256
end
when 3 # Average
row_data.each_with_index do |byte, index|
- col = index / pixel_bytes
+ col = (index / pixel_bytes).floor
upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
row_data[index] = (byte + ((left + upper)/2).floor) % 256
end
when 4 # Paeth
left = upper = upper_left = nil
row_data.each_with_index do |byte, index|
- col = index / pixel_bytes
+ col = (index / pixel_bytes).floor
left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
if row.zero?
upper = upper_left = 0
else
@@ -333,12 +338,13 @@
row_data.each_slice pixel_bytes do |slice|
s << slice
end
pixels << s
row += 1
+ row_data.clear
end
- # convert the pixel data to seperate strings for colours and alpha
+ # convert the pixel data to separate strings for colours and alpha
color_byte_size = self.colors * self.bits / 8
alpha_byte_size = alpha_channel_bits / 8
pixels.each do |this_row|
this_row.each do |pixel|
@img_data << pixel[0, color_byte_size].pack("C*")