cogl-bitmap: Fix converting formats with and without alpha channels

_cogl_bitmap_convert_format_and_premult was failing when converting
from RGBA to RGB and vice versa. _cogl_bitmap_fallback_convert
converts without altering the premult status so when choosing a new
format it would copy over the premult bit. However, it did this
regardless of whether the new format had an alpha channel so when
converting from RGBA_8888_PRE to RGB_888 it would end up inventing a
new meaningless format which would be RGB_888_PRE. This patch makes it
avoid copying the premult flag if the destination has no alpha. It
doesn't matter if it copies when the source format has no alpha
because it will always be unset.

_cogl_bitmap_convert_format_and_premult was also breaking when
converting from RGBA_8888_PRE to RGB_888 because it would think
RGB_888 is unpremultiplied and try to convert but then
_cogl_bitmap_fallback_premult wouldn't know how to do the conversion.

http://bugzilla.openedhand.com/show_bug.cgi?id=2057
This commit is contained in:
Neil Roberts 2010-03-26 22:34:56 +00:00
parent 30c4678ff4
commit f944d419a3
2 changed files with 15 additions and 3 deletions

View File

@ -359,8 +359,12 @@ _cogl_bitmap_fallback_convert (const CoglBitmap *bmp,
/* Initialize destination bitmap */
*dst_bmp = *bmp;
dst_bmp->rowstride = sizeof(guint8) * dst_bpp * dst_bmp->width;
dst_bmp->format = ((bmp->format & COGL_PREMULT_BIT) |
(dst_format & COGL_UNPREMULT_MASK));
/* Copy the premult bit if the new format has an alpha channel */
if ((dst_format & COGL_A_BIT))
dst_bmp->format = ((bmp->format & COGL_PREMULT_BIT) |
(dst_format & COGL_UNPREMULT_MASK));
else
dst_bmp->format = dst_format;
/* Allocate a new buffer to hold converted data */
dst_bmp->data = g_malloc (sizeof(guint8)

View File

@ -107,7 +107,15 @@ _cogl_bitmap_convert_format_and_premult (const CoglBitmap *bmp,
dst_bmp->data = g_memdup (bmp->data, bmp->rowstride * bmp->height);
}
if (!_cogl_bitmap_convert_premult_status (dst_bmp, dst_format))
/* We only need to do a premult conversion if both formats have an
alpha channel. If we're converting from RGB to RGBA then the
alpha will have been filled with 255 so the premult won't do
anything or if we are converting from RGBA to RGB we're losing
information so either converting or not will be wrong for
transparent pixels */
if ((dst_bmp->format & COGL_A_BIT) == COGL_A_BIT &&
(dst_format & COGL_A_BIT) == COGL_A_BIT &&
!_cogl_bitmap_convert_premult_status (dst_bmp, dst_format))
{
g_free (dst_bmp->data);
return FALSE;