lib/prawn/images/png.rb in prawn-2.0.2 vs lib/prawn/images/png.rb in prawn-2.1.0

- old
+ new

@@ -66,13 +66,11 @@ # This chunk can only occur once and it must occur after the # PLTE chunk and before the IDAT chunk @transparency = {} case @color_type when 3 - fail Errors::UnsupportedImageType, - "Pallete-based transparency in PNG is not currently supported.\n" \ - "See https://github.com/prawnpdf/prawn/issues/783" + @transparency[:palette] = data.read(chunk_size).unpack('C*') when 0 # Greyscale. Corresponding to entries in the PLTE chunk. # Grey is two bytes, range 0 .. (2 ^ bit-depth) - 1 grayval = data.read(chunk_size).unpack("n").first @transparency[:grayscale] = grayval @@ -107,15 +105,24 @@ # split the alpha channel data from the raw image data in images # where it's required. # def split_alpha_channel! - split_image_data if alpha_channel? + if alpha_channel? + if color_type == 3 + generate_alpha_channel + else + split_image_data + end + end end def alpha_channel? - @color_type == 4 || @color_type == 6 + return true if color_type == 4 || color_type == 6 + return @transparency.any? if color_type == 3 + + false end # Build a PDF object representing this image in +document+, and return # a Reference to it. # @@ -282,9 +289,40 @@ alpha.write data.read(alpha_bytes) end end @img_data = color_data + end + + def generate_alpha_channel + alpha_palette = Hash.new(0xff) + 0.upto(palette.bytesize / 3) do |n| + alpha_palette[n] = @transparency[:palette][n] || 0xff + end + + scanline_length = width + 1 + scanlines = @img_data.bytesize / scanline_length + pixels = width * height + + data = StringIO.new(@img_data) + data.binmode + + @alpha_channel = [0x00].pack('C') * (pixels + scanlines) + alpha = StringIO.new(@alpha_channel) + alpha.binmode + + scanlines.times do |line| + data.seek(line * scanline_length) + + filter = data.getbyte + + alpha.putc filter + + width.times do + color = data.read(1).unpack('C').first + alpha.putc alpha_palette[color] + end + end end end end end