diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2008-04-21 18:20:16 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2008-04-21 18:35:07 +0100 |
commit | f2f91db131e7c7df1e87bcd41ae17c07429bbcb8 (patch) | |
tree | 83d4e86478428a15b56469b261da3c7c58f14771 /src/cairo-png.c | |
parent | ea6dbfd36f2182fda16cb82bca92007e0f7b8d77 (diff) |
[cairo-png] Create an ARGB32 surface for paletted PNGs.
jeremie54 reported a regression in the handling of transparent paletted
PNGs beween 1.4.14 and 1.6.4. This was caused by the change to load
opaque PNGs into a RGB24 image surface, which made the assumption that
indexed PNGs were opaque. However, alpha/transparency in PNG is more
complicated, as PNG uses a tRNS chunk to supply transparency data for
paletted images and other image types that don't need a full alpha
channel. Therefore if the PNG contains a tRNS chunk always generate an
ARGB32 surface.
Diffstat (limited to 'src/cairo-png.c')
-rw-r--r-- | src/cairo-png.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/cairo-png.c b/src/cairo-png.c index 0db4b090..3ec85c06 100644 --- a/src/cairo-png.c +++ b/src/cairo-png.c @@ -434,6 +434,7 @@ read_png (png_rw_ptr read_func, unsigned int i; cairo_format_t format; cairo_status_t status; + cairo_bool_t need_alpha; /* XXX: Perhaps we'll want some other error handlers? */ png = png_create_read_struct (PNG_LIBPNG_VER_STRING, @@ -485,8 +486,11 @@ read_png (png_rw_ptr read_func, } /* transform transparency to alpha */ - if (png_get_valid (png, info, PNG_INFO_tRNS)) + need_alpha = FALSE; + if (png_get_valid (png, info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha (png); + need_alpha = TRUE; + } if (depth == 16) png_set_strip_16 (png); @@ -513,11 +517,16 @@ read_png (png_rw_ptr read_func, break; case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_PALETTE: case PNG_COLOR_TYPE_RGB: - format = CAIRO_FORMAT_RGB24; - png_set_read_user_transform_fn (png, convert_bytes_to_data); - png_set_filler (png, 0xff, PNG_FILLER_AFTER); + case PNG_COLOR_TYPE_PALETTE: + if (need_alpha) { + format = CAIRO_FORMAT_ARGB32; + png_set_read_user_transform_fn (png, premultiply_data); + } else { + format = CAIRO_FORMAT_RGB24; + png_set_read_user_transform_fn (png, convert_bytes_to_data); + png_set_filler (png, 0xff, PNG_FILLER_AFTER); + } break; } |