mutter/common/cogl-bitmap.c
Owen W. Taylor b0887a0d75 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>
2009-06-11 14:17:51 +01:00

209 lines
5.0 KiB
C

/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2007,2008,2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl.h"
#include "cogl-internal.h"
#include "cogl-bitmap-private.h"
#include <string.h>
static void _cogl_bitmap_free (CoglBitmap *bmp);
COGL_HANDLE_DEFINE (Bitmap, bitmap);
static void
_cogl_bitmap_free (CoglBitmap *bmp)
{
g_free (bmp->data);
g_free (bmp);
}
gint
_cogl_get_format_bpp (CoglPixelFormat format)
{
gint bpp_lut[] = {
0, /* invalid */
1, /* A_8 */
3, /* 888 */
4, /* 8888 */
2, /* 565 */
2, /* 4444 */
2, /* 5551 */
2, /* YUV */
1 /* G_8 */
};
return bpp_lut [format & COGL_UNORDERED_MASK];
}
gboolean
_cogl_bitmap_convert_and_premult (const CoglBitmap *bmp,
CoglBitmap *dst_bmp,
CoglPixelFormat dst_format)
{
CoglBitmap tmp_bmp = *bmp;
CoglBitmap new_bmp = *bmp;
gboolean new_bmp_owner = FALSE;
/* Is base format different (not considering premult status)? */
if ((bmp->format & COGL_UNPREMULT_MASK) !=
(dst_format & COGL_UNPREMULT_MASK))
{
/* Try converting using imaging library */
if (!_cogl_bitmap_convert (&new_bmp, &tmp_bmp, dst_format))
{
/* ... or try fallback */
if (!_cogl_bitmap_fallback_convert (&new_bmp, &tmp_bmp, dst_format))
return FALSE;
}
/* Update bitmap with new data */
new_bmp = tmp_bmp;
new_bmp_owner = TRUE;
}
/* Do we need to unpremultiply */
if ((bmp->format & COGL_PREMULT_BIT) > 0 &&
(dst_format & COGL_PREMULT_BIT) == 0)
{
/* Try unpremultiplying using imaging library */
if (!_cogl_bitmap_unpremult (&new_bmp, &tmp_bmp))
{
/* ... or try fallback */
if (!_cogl_bitmap_fallback_unpremult (&new_bmp, &tmp_bmp))
{
if (new_bmp_owner)
g_free (new_bmp.data);
return FALSE;
}
}
/* Update bitmap with new data */
if (new_bmp_owner)
g_free (new_bmp.data);
new_bmp = tmp_bmp;
new_bmp_owner = TRUE;
}
/* Do we need to premultiply */
if ((bmp->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))
{
if (new_bmp_owner)
g_free (new_bmp.data);
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 */
*dst_bmp = new_bmp;
return TRUE;
}
void
_cogl_bitmap_copy_subregion (CoglBitmap *src,
CoglBitmap *dst,
gint src_x,
gint src_y,
gint dst_x,
gint dst_y,
gint width,
gint height)
{
guchar *srcdata;
guchar *dstdata;
gint bpp;
gint line;
/* Intended only for fast copies when format is equal! */
g_assert (src->format == dst->format);
bpp = _cogl_get_format_bpp (src->format);
srcdata = src->data + src_y * src->rowstride + src_x * bpp;
dstdata = dst->data + dst_y * dst->rowstride + dst_x * bpp;
for (line=0; line<height; ++line)
{
memcpy (dstdata, srcdata, width * bpp);
srcdata += src->rowstride;
dstdata += dst->rowstride;
}
}
gboolean
cogl_bitmap_get_size_from_file (const gchar *filename,
gint *width,
gint *height)
{
return _cogl_bitmap_get_size_from_file (filename, width, height);
}
CoglHandle
cogl_bitmap_new_from_file (const gchar *filename,
GError **error)
{
CoglBitmap bmp;
CoglBitmap *ret;
g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
/* Try loading with imaging backend */
if (!_cogl_bitmap_from_file (&bmp, filename, error))
{
/* Try fallback */
if (!_cogl_bitmap_fallback_from_file (&bmp, filename))
return NULL;
else if (error && *error)
{
g_error_free (*error);
*error = NULL;
}
}
ret = g_memdup (&bmp, sizeof (CoglBitmap));
return _cogl_bitmap_handle_new (ret);
}