lib/prawn/images/png.rb in prawn-0.1.2 vs lib/prawn/images/png.rb in prawn-0.2.0

- old
+ new

@@ -28,10 +28,11 @@ data.read(8) # Skip the default header @palette = "" @img_data = "" + @transparency = {} loop do chunk_size = data.read(4).unpack("N")[0] section = data.read(4) case section @@ -59,20 +60,21 @@ when 3 # Indexed colour, RGB. Each byte in this chunk is an alpha for # the palette index in the PLTE ("palette") chunk up until the # last non-opaque entry. Set up an array, stretching over all # palette entries which will be 0 (opaque) or 1 (transparent). - @transparency[:type] = 'indexed' - @transparency[:data] = data.read(chunk_size).unpack("C*") + @transparency[:indexed] = data.read(chunk_size).unpack("C*") + short = 255 - @transparency[:indexed].size + @transparency[:indexed] += ([255] * short) if short > 0 when 0 # Greyscale. Corresponding to entries in the PLTE chunk. # Grey is two bytes, range 0 .. (2 ^ bit-depth) - 1 - @transparency[:grayscale] = data.read(2).unpack("n") - @transparency[:type] = 'indexed' + grayval = data.read(chunk_size).unpack("n").first + @transparency[:grayscale] = grayval when 2 # True colour with proper alpha channel. - @transparency[:rgb] = data.read(6).unpack("nnn") + @transparency[:rgb] = data.read(chunk_size).unpack("nnn") end when 'IEND' # we've got everything we need, exit the loop break else @@ -86,43 +88,33 @@ # if our img_data contains alpha channel data, split it out unfilter_image_data if alpha_channel? end def pixel_bytes - case @color_type - when 0, 4 then 1 + @pixel_bytes ||= case @color_type + when 0, 3, 4 then 1 when 1, 2, 6 then 3 end end private def alpha_channel? @color_type == 4 || @color_type == 6 end - def paeth(a, b, c) # left, above, upper left - p = a + b - c - pa = (p - a).abs - pb = (p - b).abs - pc = (p - c).abs - - return a if pa <= pb && pa <= pc - return b if pb <= pc - c - end - def unfilter_image_data data = Zlib::Inflate.inflate(@img_data).unpack 'C*' @img_data = "" @alpha_channel = "" # each pixel has the color bytes, plus a byte of alpha channel pixel_length = pixel_bytes + 1 scanline_length = pixel_length * @width + 1 # for filter row = 0 - pixels = [] + pixels = [] + paeth, pa, pb, pc = nil until data.empty? do row_data = data.slice! 0, scanline_length filter = row_data.shift case filter when 0 # None @@ -150,29 +142,42 @@ left = upper = upper_left = nil row_data.each_with_index do |byte, index| col = index / pixel_length left = index < pixel_length ? 0 : row_data[index - pixel_length] - if row == 0 then + if row.zero? upper = upper_left = 0 else upper = pixels[row-1][col][index % pixel_length] - upper_left = col == 0 ? 0 : + upper_left = col.zero? ? 0 : pixels[row-1][col-1][index % pixel_length] end - paeth = paeth left, upper, upper_left + p = left + upper - upper_left + pa = (p - left).abs + pb = (p - upper).abs + pc = (p - upper_left).abs + + paeth = if pa <= pb && pa <= pc + left + elsif pb <= pc + upper + else + upper_left + end + row_data[index] = (byte + paeth) % 256 #p [byte, paeth, row_data[index]] end else raise ArgumentError, "Invalid filter algorithm #{filter}" end - pixels << [] + s = [] row_data.each_slice pixel_length do |slice| - pixels.last << slice + s << slice end + pixels << s row += 1 end # convert the pixel data to seperate strings for colours and alpha pixels.each do |row|