Skip to content

Commit

Permalink
improving PNG transparency support
Browse files Browse the repository at this point in the history
- add support for transparency in Greyscale and RGB images
- Just need to add transparency support for indexed images now
  • Loading branch information
yob authored and practicingruby committed Aug 18, 2008
1 parent 0439e04 commit b66e99f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 10 deletions.
30 changes: 26 additions & 4 deletions lib/prawn/images.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,35 @@ def build_png_object(data, png)
:DeviceRGB,
(png.palette.size / 3) -1,
palette_obj]
end

# *************************************
# add transparency data if necessary
# *************************************

# add transparency data if necessary
#if png.transparency && png.transparency[:type] == 'indexed'
# obj.data[:Mask] = png.transparency[:data]
#end
# For PNG color types 0, 2 and 3, the transparency data is stored in
# a dedicated PNG chunk, and is exposed via the transparency attribute
# of the PNG class.
if png.transparency[:grayscale]
# Use Color Key Masking (spec section 4.8.5)
# - An array with N elements, where N is two times the number of color
# components.
obj.data[:Mask] = png.transparency[:grayscale].collect { |val| [val,val] }
elsif png.transparency[:rgb]
# Use Color Key Masking (spec section 4.8.5)
# - An array with N elements, where N is two times the number of color
# components.
obj.data[:Mask] = png.transparency[:rgb].collect { |val| [val,val] }.flatten
elsif png.transparency[:indexed]
# TODO: broken. I was attempting to us Color Key Masking, but I think
# we need to construct an SMask i think. Maybe do it inside
# the PNG class, and store it in alpha_channel
#obj.data[:Mask] = png.transparency[:indexed]
end

# For PNG color types 4 and 6, the transparency data is stored as a alpha
# channel mixed in with the main image data. The PNG class seperates
# it out for us and makes it available via the alpha_channel attribute
if png.alpha_channel
smask_obj = ref(:Type => :XObject,
:Subtype => :Image,
Expand Down
13 changes: 7 additions & 6 deletions lib/prawn/images/png.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def initialize(data)

@palette = ""
@img_data = ""
@transparency = {}

loop do
chunk_size = data.read(4).unpack("N")[0]
Expand Down Expand Up @@ -61,16 +62,16 @@ def initialize(data)
# 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'
@transparency[:grayscale] = data.read(chunk_size).unpack("n")
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
Expand All @@ -89,7 +90,7 @@ def initialize(data)

def pixel_bytes
case @color_type
when 0, 4 then 1
when 0, 3, 4 then 1
when 1, 2, 6 then 3
end
end
Expand Down

0 comments on commit b66e99f

Please sign in to comment.