mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
Implement premultiplication for CoglBitmap
cogl-bitmap.c cogl-bitmap-pixbuf.c cogl-bitmap-fallback.c cogl-bitmap-private.h: Add _cogl_bitmap_can_premult(), _cogl_bitmap_premult() and implement a reasonably fast implementation in the "fallback" code. http://bugzilla.openedhand.com/show_bug.cgi?id=1406 Signed-off-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
parent
dcc4f14169
commit
b0887a0d75
@ -180,6 +180,41 @@ _cogl_unpremult_alpha_first (const guchar *src, guchar *dst)
|
|||||||
dst[3] = ((((gulong) src[3] >> 0) & 0xff) * 255 ) / alpha;
|
dst[3] = ((((gulong) src[3] >> 0) & 0xff) * 255 ) / alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No division form of floor((c*a + 128)/255) (I first encountered
|
||||||
|
* this in the RENDER implementation in the X server.) Being exact
|
||||||
|
* is important for a == 255 - we want to get exactly c.
|
||||||
|
*/
|
||||||
|
#define MULT(d,c,a,t) G_STMT_START { t = c * a + 128; d = ((t >> 8) + t) >> 8; } G_STMT_END
|
||||||
|
|
||||||
|
inline static void
|
||||||
|
_cogl_premult_alpha_last (const guchar *src, guchar *dst)
|
||||||
|
{
|
||||||
|
guchar alpha = src[3];
|
||||||
|
/* Using a separate temporary per component has given slightly better
|
||||||
|
* code generation with GCC in the past; it shouldn't do any worse in
|
||||||
|
* any case.
|
||||||
|
*/
|
||||||
|
guint t1, t2, t3;
|
||||||
|
MULT(dst[0], src[0], alpha, t1);
|
||||||
|
MULT(dst[1], src[1], alpha, t2);
|
||||||
|
MULT(dst[2], src[2], alpha, t3);
|
||||||
|
dst[3] = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void
|
||||||
|
_cogl_premult_alpha_first (const guchar *src, guchar *dst)
|
||||||
|
{
|
||||||
|
guchar alpha = src[0];
|
||||||
|
guint t1, t2, t3;
|
||||||
|
|
||||||
|
dst[0] = alpha;
|
||||||
|
MULT(dst[1], src[1], alpha, t1);
|
||||||
|
MULT(dst[2], src[2], alpha, t2);
|
||||||
|
MULT(dst[3], src[3], alpha, t3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MULT
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_can_convert (CoglPixelFormat src, CoglPixelFormat dst)
|
_cogl_bitmap_fallback_can_convert (CoglPixelFormat src, CoglPixelFormat dst)
|
||||||
{
|
{
|
||||||
@ -211,6 +246,12 @@ _cogl_bitmap_fallback_can_unpremult (CoglPixelFormat format)
|
|||||||
return ((format & COGL_UNORDERED_MASK) == COGL_PIXEL_FORMAT_32);
|
return ((format & COGL_UNORDERED_MASK) == COGL_PIXEL_FORMAT_32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_fallback_can_premult (CoglPixelFormat format)
|
||||||
|
{
|
||||||
|
return ((format & COGL_UNORDERED_MASK) == COGL_PIXEL_FORMAT_32);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_convert (const CoglBitmap *bmp,
|
_cogl_bitmap_fallback_convert (const CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
CoglBitmap *dst_bmp,
|
||||||
@ -358,6 +399,58 @@ _cogl_bitmap_fallback_unpremult (const CoglBitmap *bmp,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_fallback_premult (const CoglBitmap *bmp,
|
||||||
|
CoglBitmap *dst_bmp)
|
||||||
|
{
|
||||||
|
guchar *src;
|
||||||
|
guchar *dst;
|
||||||
|
gint bpp;
|
||||||
|
gint x,y;
|
||||||
|
|
||||||
|
/* Make sure format supported for un-premultiplication */
|
||||||
|
if (!_cogl_bitmap_fallback_can_premult (bmp->format))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
bpp = _cogl_get_format_bpp (bmp->format);
|
||||||
|
|
||||||
|
/* Initialize destination bitmap */
|
||||||
|
*dst_bmp = *bmp;
|
||||||
|
dst_bmp->format = (bmp->format & COGL_UNPREMULT_MASK);
|
||||||
|
|
||||||
|
/* Allocate a new buffer to hold converted data */
|
||||||
|
dst_bmp->data = g_malloc (sizeof(guchar)
|
||||||
|
* dst_bmp->height
|
||||||
|
* dst_bmp->rowstride);
|
||||||
|
|
||||||
|
for (y = 0; y < bmp->height; y++)
|
||||||
|
{
|
||||||
|
src = (guchar*)bmp->data + y * bmp->rowstride;
|
||||||
|
dst = (guchar*)dst_bmp->data + y * dst_bmp->rowstride;
|
||||||
|
|
||||||
|
if (bmp->format & COGL_AFIRST_BIT)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bmp->width; x++)
|
||||||
|
{
|
||||||
|
_cogl_premult_alpha_first (src, dst);
|
||||||
|
src += bpp;
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (x = 0; x < bmp->width; x++)
|
||||||
|
{
|
||||||
|
_cogl_premult_alpha_last (src, dst);
|
||||||
|
src += bpp;
|
||||||
|
dst += bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_fallback_from_file (CoglBitmap *bmp,
|
||||||
const gchar *filename)
|
const gchar *filename)
|
||||||
|
@ -49,6 +49,12 @@ _cogl_bitmap_can_unpremult (CoglPixelFormat format)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_can_premult (CoglPixelFormat format)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_convert (const CoglBitmap *bmp,
|
_cogl_bitmap_convert (const CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
CoglBitmap *dst_bmp,
|
||||||
@ -64,6 +70,13 @@ _cogl_bitmap_unpremult (const CoglBitmap *bmp,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_premult (const CoglBitmap *bmp,
|
||||||
|
CoglBitmap *dst_bmp)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_QUARTZ
|
#ifdef USE_QUARTZ
|
||||||
|
|
||||||
/* lacking GdkPixbuf and other useful GError domains, define one of our own */
|
/* lacking GdkPixbuf and other useful GError domains, define one of our own */
|
||||||
|
@ -52,6 +52,12 @@ _cogl_bitmap_can_unpremult (CoglPixelFormat format);
|
|||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_can_unpremult (CoglPixelFormat format);
|
_cogl_bitmap_fallback_can_unpremult (CoglPixelFormat format);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_can_premult (CoglPixelFormat format);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_fallback_can_premult (CoglPixelFormat format);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_convert (const CoglBitmap *bmp,
|
_cogl_bitmap_convert (const CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
CoglBitmap *dst_bmp,
|
||||||
@ -69,6 +75,14 @@ gboolean
|
|||||||
_cogl_bitmap_fallback_unpremult (const CoglBitmap *bmp,
|
_cogl_bitmap_fallback_unpremult (const CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp);
|
CoglBitmap *dst_bmp);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_premult (const CoglBitmap *bmp,
|
||||||
|
CoglBitmap *dst_bmp);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_bitmap_fallback_premult (const CoglBitmap *bmp,
|
||||||
|
CoglBitmap *dst_bmp);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_from_file (CoglBitmap *bmp,
|
||||||
const gchar *filename,
|
const gchar *filename,
|
||||||
|
@ -87,8 +87,8 @@ _cogl_bitmap_convert_and_premult (const CoglBitmap *bmp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do we need to unpremultiply */
|
/* Do we need to unpremultiply */
|
||||||
if ((bmp->format & COGL_PREMULT_BIT) == 0 &&
|
if ((bmp->format & COGL_PREMULT_BIT) > 0 &&
|
||||||
(dst_format & COGL_PREMULT_BIT) > 0)
|
(dst_format & COGL_PREMULT_BIT) == 0)
|
||||||
{
|
{
|
||||||
/* Try unpremultiplying using imaging library */
|
/* Try unpremultiplying using imaging library */
|
||||||
if (!_cogl_bitmap_unpremult (&new_bmp, &tmp_bmp))
|
if (!_cogl_bitmap_unpremult (&new_bmp, &tmp_bmp))
|
||||||
@ -112,15 +112,29 @@ _cogl_bitmap_convert_and_premult (const CoglBitmap *bmp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do we need to premultiply */
|
/* Do we need to premultiply */
|
||||||
if ((bmp->format & COGL_PREMULT_BIT) > 0 &&
|
if ((bmp->format & COGL_PREMULT_BIT) == 0 &&
|
||||||
(dst_format & COGL_PREMULT_BIT) == 0)
|
(dst_format & COGL_PREMULT_BIT) > 0)
|
||||||
|
{
|
||||||
|
/* Try premultiplying using imaging library */
|
||||||
|
if (!_cogl_bitmap_premult (&new_bmp, &tmp_bmp))
|
||||||
|
{
|
||||||
|
/* ... or try fallback */
|
||||||
|
if (!_cogl_bitmap_fallback_premult (&new_bmp, &tmp_bmp))
|
||||||
{
|
{
|
||||||
/* FIXME: implement premultiplication */
|
|
||||||
if (new_bmp_owner)
|
if (new_bmp_owner)
|
||||||
g_free (new_bmp.data);
|
g_free (new_bmp.data);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update bitmap with new data */
|
||||||
|
if (new_bmp_owner)
|
||||||
|
g_free (new_bmp.data);
|
||||||
|
|
||||||
|
new_bmp = tmp_bmp;
|
||||||
|
new_bmp_owner = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Output new bitmap info */
|
/* Output new bitmap info */
|
||||||
*dst_bmp = new_bmp;
|
*dst_bmp = new_bmp;
|
||||||
|
Loading…
Reference in New Issue
Block a user