bitmap: Adds cogl_android_bitmap_new_from_asset()

This adds some android specific api for creating a CoglBitmap from an
Android asset.

As part of the work it also seemed like a good time to change the
internal bitmap constructors to take an explicit CoglContext argument
and so the public cogl_bitmap_new_from_file() api was also changed
accordingly to take a CoglContext pointer as the first argument.

Reviewed-by: Neil Roberts <neil@linux.intel.com>

(cherry picked from commit 099d6d1b505b55bbd09c50d081deb41ab5764e19)

  Since we aren't able to break APIs on the 1.12 branch this cherry-pick
  skips the change to cogl_bitmap_new_from_file()
This commit is contained in:
Robert Bragg 2012-05-09 19:43:06 +01:00
parent d1dc4e1e0b
commit 1686e754a7
5 changed files with 239 additions and 36 deletions

View File

@ -29,6 +29,7 @@
#include "cogl-internal.h" #include "cogl-internal.h"
#include "cogl-bitmap-private.h" #include "cogl-bitmap-private.h"
#include "cogl-context-private.h" #include "cogl-context-private.h"
#include "cogl-private.h"
#include <string.h> #include <string.h>
@ -56,8 +57,9 @@ _cogl_bitmap_get_size_from_file (const char *filename,
/* the error does not contain the filename as the caller already has it */ /* the error does not contain the filename as the caller already has it */
CoglBitmap * CoglBitmap *
_cogl_bitmap_from_file (const char *filename, _cogl_bitmap_from_file (CoglContext *ctx,
GError **error) const char *filename,
GError **error)
{ {
CFURLRef url; CFURLRef url;
CGImageSourceRef image_source; CGImageSourceRef image_source;
@ -70,11 +72,6 @@ _cogl_bitmap_from_file (const char *filename,
CGContextRef bitmap_context; CGContextRef bitmap_context;
CoglBitmap *bmp; CoglBitmap *bmp;
_COGL_GET_CONTEXT (ctx, NULL);
g_assert (filename != NULL);
g_assert (error == NULL || *error == NULL);
url = CFURLCreateFromFileSystemRepresentation (NULL, url = CFURLCreateFromFileSystemRepresentation (NULL,
(guchar *) filename, (guchar *) filename,
strlen (filename), strlen (filename),
@ -173,8 +170,9 @@ _cogl_bitmap_get_size_from_file (const char *filename,
} }
CoglBitmap * CoglBitmap *
_cogl_bitmap_from_file (const char *filename, _cogl_bitmap_from_file (CoglContext *ctx,
GError **error) const char *filename,
GError **error)
{ {
static CoglUserDataKey pixbuf_key; static CoglUserDataKey pixbuf_key;
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
@ -188,10 +186,6 @@ _cogl_bitmap_from_file (const char *filename,
int n_channels; int n_channels;
CoglBitmap *bmp; CoglBitmap *bmp;
_COGL_GET_CONTEXT (ctx, NULL);
_COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE);
/* Load from file using GdkPixbuf */ /* Load from file using GdkPixbuf */
pixbuf = gdk_pixbuf_new_from_file (filename, error); pixbuf = gdk_pixbuf_new_from_file (filename, error);
if (pixbuf == NULL) if (pixbuf == NULL)
@ -269,38 +263,187 @@ _cogl_bitmap_get_size_from_file (const char *filename,
return TRUE; return TRUE;
} }
CoglBitmap * /* stb_image.c supports an STBI_grey_alpha format which we don't have
_cogl_bitmap_from_file (const char *filename, * a corresponding CoglPixelFormat for so as a special case we
GError **error) * convert this to rgba8888.
*
* If we have a use case where this is an important format to consider
* then it could be worth adding a corresponding CoglPixelFormat
* instead.
*/
static uint8_t *
convert_ra_88_to_rgba_8888 (uint8_t *pixels,
int width,
int height)
{
int x, y;
uint8_t *buf;
size_t in_stride = width * 2;
size_t out_stride = width * 4;
buf = malloc (width * height * 4);
if (buf)
return NULL;
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
{
uint8_t *src = pixels + in_stride * y + 2 * x;
uint8_t *dst = buf + out_stride * y + 4 * x;
dst[0] = src[0];
dst[1] = src[0];
dst[2] = src[0];
dst[3] = src[1];
}
return buf;
}
static CoglBitmap *
_cogl_bitmap_new_from_stb_pixels (CoglContext *ctx,
uint8_t *pixels,
int stb_pixel_format,
int width,
int height,
GError **error)
{ {
static CoglUserDataKey bitmap_data_key; static CoglUserDataKey bitmap_data_key;
CoglBitmap *bmp; CoglBitmap *bmp;
int stb_pixel_format; CoglPixelFormat cogl_format;
int width; size_t stride;
int height;
uint8_t *pixels;
_COGL_GET_CONTEXT (ctx, NULL);
_COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE);
/* Load from file using stb */
pixels = stbi_load (filename,
&width, &height, &stb_pixel_format,
STBI_rgb_alpha);
if (pixels == NULL) if (pixels == NULL)
return FALSE; {
g_set_error_literal (error,
COGL_BITMAP_ERROR,
COGL_BITMAP_ERROR_FAILED,
"Failed to load image with stb image library");
return NULL;
}
switch (stb_pixel_format)
{
case STBI_grey:
cogl_format = COGL_PIXEL_FORMAT_A_8;
break;
case STBI_grey_alpha:
{
uint8_t *tmp = pixels;
pixels = convert_ra_88_to_rgba_8888 (pixels, width, height);
free (tmp);
if (!pixels)
{
g_set_error_literal (error,
COGL_BITMAP_ERROR,
COGL_BITMAP_ERROR_FAILED,
"Failed to alloc memory to convert "
"gray_alpha to rgba8888");
return NULL;
}
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888;
break;
}
case STBI_rgb:
cogl_format = COGL_PIXEL_FORMAT_RGB_888;
break;
case STBI_rgb_alpha:
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888;
break;
default:
g_warn_if_reached ();
return NULL;
}
stride = width * _cogl_pixel_format_get_bytes_per_pixel (cogl_format);
/* Store bitmap info */ /* Store bitmap info */
bmp = cogl_bitmap_new_for_data (ctx, bmp = cogl_bitmap_new_for_data (ctx,
width, height, width, height,
COGL_PIXEL_FORMAT_RGBA_8888, cogl_format,
width * 4, /* rowstride */ stride,
pixels); pixels);
/* Register a destroy function so the pixel data will be freed /* Register a destroy function so the pixel data will be freed
automatically when the bitmap object is destroyed */ automatically when the bitmap object is destroyed */
cogl_object_set_user_data (COGL_OBJECT (bmp), &bitmap_data_key, pixels, free); cogl_object_set_user_data (COGL_OBJECT (bmp), &bitmap_data_key, pixels, free);
return bmp; return bmp;
} }
CoglBitmap *
_cogl_bitmap_from_file (CoglContext *ctx,
const char *filename,
GError **error)
{
int stb_pixel_format;
int width;
int height;
uint8_t *pixels;
pixels = stbi_load (filename,
&width, &height, &stb_pixel_format,
STBI_default);
return _cogl_bitmap_new_from_stb_pixels (ctx, pixels, stb_pixel_format,
width, height,
error);
}
#ifdef COGL_HAS_ANDROID_SUPPORT
CoglBitmap *
_cogl_android_bitmap_new_from_asset (CoglContext *ctx,
AAssetManager *manager,
const char *filename,
GError **error)
{
AAsset *asset;
const void *data;
off_t len;
int stb_pixel_format;
int width;
int height;
uint8_t *pixels;
CoglBitmap *bmp;
asset = AAssetManager_open (manager, filename, AASSET_MODE_BUFFER);
if (!asset)
{
g_set_error_literal (error,
COGL_BITMAP_ERROR,
COGL_BITMAP_ERROR_FAILED,
"Failed to open asset");
return NULL;
}
data = AAsset_getBuffer (asset);
if (!data)
{
g_set_error_literal (error,
COGL_BITMAP_ERROR,
COGL_BITMAP_ERROR_FAILED,
"Failed to ::getBuffer from asset");
return NULL;
}
len = AAsset_getLength (asset);
pixels = stbi_load_from_memory (data, len,
&width, &height,
&stb_pixel_format, STBI_default);
bmp = _cogl_bitmap_new_from_stb_pixels (ctx, pixels, stb_pixel_format,
width, height,
error);
AAsset_close (asset);
return bmp;
}
#endif
#endif #endif

View File

@ -32,6 +32,10 @@
#include "cogl-buffer.h" #include "cogl-buffer.h"
#include "cogl-bitmap.h" #include "cogl-bitmap.h"
#ifdef COGL_HAS_ANDROID_SUPPORT
#include <android/asset_manager.h>
#endif
struct _CoglBitmap struct _CoglBitmap
{ {
CoglObject _parent; CoglObject _parent;
@ -103,8 +107,17 @@ _cogl_bitmap_convert_into_bitmap (CoglBitmap *src_bmp,
CoglBitmap *dst_bmp); CoglBitmap *dst_bmp);
CoglBitmap * CoglBitmap *
_cogl_bitmap_from_file (const char *filename, _cogl_bitmap_from_file (CoglContext *ctx,
GError **error); const char *filename,
GError **error);
#ifdef COGL_HAS_ANDROID_SUPPORT
CoglBitmap *
_cogl_android_bitmap_new_from_asset (CoglContext *ctx,
AAssetManager *manager,
const char *filename,
GError **error);
#endif
CoglBool CoglBool
_cogl_bitmap_unpremult (CoglBitmap *dst_bmp); _cogl_bitmap_unpremult (CoglBitmap *dst_bmp);

View File

@ -227,12 +227,15 @@ _cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
} }
CoglBitmap * CoglBitmap *
cogl_bitmap_new_from_file (const char *filename, cogl_bitmap_new_from_file (const char *filename,
GError **error) GError **error)
{ {
_COGL_GET_CONTEXT (ctx, NULL);
_COGL_RETURN_VAL_IF_FAIL (filename != NULL, NULL);
_COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL);
return _cogl_bitmap_from_file (filename, error); return _cogl_bitmap_from_file (ctx, filename, error);
} }
CoglBitmap * CoglBitmap *
@ -293,6 +296,22 @@ cogl_bitmap_new_with_size (CoglContext *context,
return bitmap; return bitmap;
} }
#ifdef COGL_HAS_ANDROID_SUPPORT
CoglBitmap *
cogl_android_bitmap_new_from_asset (CoglContext *ctx,
AAssetManager *manager,
const char *filename,
GError **error)
{
_COGL_RETURN_VAL_IF_FAIL (ctx != NULL, NULL);
_COGL_RETURN_VAL_IF_FAIL (manager != NULL, NULL);
_COGL_RETURN_VAL_IF_FAIL (filename != NULL, NULL);
_COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL);
return _cogl_android_bitmap_new_from_asset (ctx, manager, filename, error);
}
#endif
CoglPixelFormat CoglPixelFormat
cogl_bitmap_get_format (CoglBitmap *bitmap) cogl_bitmap_get_format (CoglBitmap *bitmap)
{ {

View File

@ -33,6 +33,10 @@
#include <cogl/cogl-context.h> #include <cogl/cogl-context.h>
#include <cogl/cogl-pixel-buffer.h> #include <cogl/cogl-pixel-buffer.h>
#ifdef COGL_HAS_ANDROID_SUPPORT
#include <android/asset_manager.h>
#endif
G_BEGIN_DECLS G_BEGIN_DECLS
typedef struct _CoglBitmap CoglBitmap; typedef struct _CoglBitmap CoglBitmap;
@ -65,6 +69,28 @@ CoglBitmap *
cogl_bitmap_new_from_file (const char *filename, cogl_bitmap_new_from_file (const char *filename,
GError **error); GError **error);
#ifdef COGL_HAS_ANDROID_SUPPORT
/**
* cogl_android_bitmap_new_from_asset:
* @context: A #CoglContext
* @manager: An Android Asset Manager.
* @filename: The file name for the asset
* @error: A return location for a GError exception.
*
* Loads an Android asset into a newly allocated #CoglBitmap.
*
* Return value: A newly allocated #CoglBitmap holding the image data of the
* specified asset.
*
* Since: 2.0
*/
CoglBitmap *
cogl_android_bitmap_new_from_asset (CoglContext *context,
AAssetManager *manager,
const char *filename,
GError **error);
#endif
#if defined (COGL_ENABLE_EXPERIMENTAL_API) #if defined (COGL_ENABLE_EXPERIMENTAL_API)
/** /**

View File

@ -450,6 +450,8 @@ cogl_texture_new_from_file (const char *filename,
CoglTexture *texture = NULL; CoglTexture *texture = NULL;
CoglPixelFormat src_format; CoglPixelFormat src_format;
_COGL_GET_CONTEXT (ctx, NULL);
_COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL);
bmp = cogl_bitmap_new_from_file (filename, error); bmp = cogl_bitmap_new_from_file (filename, error);