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*")