4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2007,2008,2009 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
28 #include "cogl-util.h"
29 #include "cogl-internal.h"
30 #include "cogl-bitmap-private.h"
31 #include "cogl-context-private.h"
36 #include <ApplicationServices/ApplicationServices.h>
37 #elif defined(USE_GDKPIXBUF)
38 #include <gdk-pixbuf/gdk-pixbuf.h>
44 _cogl_bitmap_get_size_from_file (const char *filename,
57 /* the error does not contain the filename as the caller already has it */
59 _cogl_bitmap_from_file (const char *filename,
63 CGImageSourceRef image_source;
67 gsize width, height, rowstride;
69 CGColorSpaceRef color_space;
70 CGContextRef bitmap_context;
73 _COGL_GET_CONTEXT (ctx, NULL);
75 g_assert (filename != NULL);
76 g_assert (error == NULL || *error == NULL);
78 url = CFURLCreateFromFileSystemRepresentation (NULL,
82 image_source = CGImageSourceCreateWithURL (url, NULL);
86 if (image_source == NULL)
88 /* doesn't exist, not readable, etc. */
89 g_set_error_literal (error,
91 COGL_BITMAP_ERROR_FAILED,
92 g_strerror (save_errno));
96 /* Unknown images would be cleanly caught as zero width/height below, but try
97 * to provide better error message
99 type = CGImageSourceGetType (image_source);
102 CFRelease (image_source);
103 g_set_error_literal (error,
105 COGL_BITMAP_ERROR_UNKNOWN_TYPE,
106 "Unknown image type");
112 image = CGImageSourceCreateImageAtIndex (image_source, 0, NULL);
113 CFRelease (image_source);
115 width = CGImageGetWidth (image);
116 height = CGImageGetHeight (image);
117 if (width == 0 || height == 0)
119 /* incomplete or corrupt */
121 g_set_error_literal (error,
123 COGL_BITMAP_ERROR_CORRUPT_IMAGE,
124 "Image has zero width or height");
128 /* allocate buffer big enough to hold pixel data */
129 bmp = _cogl_bitmap_new_with_malloc_buffer (ctx,
131 COGL_PIXEL_FORMAT_ARGB_8888);
132 rowstride = cogl_bitmap_get_rowstride (bmp);
133 out_data = _cogl_bitmap_map (bmp,
134 COGL_BUFFER_ACCESS_WRITE,
135 COGL_BUFFER_MAP_HINT_DISCARD);
137 /* render to buffer */
138 color_space = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
139 bitmap_context = CGBitmapContextCreate (out_data,
141 rowstride, color_space,
142 kCGImageAlphaPremultipliedFirst);
143 CGColorSpaceRelease (color_space);
146 const CGRect rect = {{0, 0}, {width, height}};
148 CGContextDrawImage (bitmap_context, rect, image);
151 CGImageRelease (image);
152 CGContextRelease (bitmap_context);
154 _cogl_bitmap_unmap (bmp);
156 /* store bitmap info */
160 #elif defined(USE_GDKPIXBUF)
163 _cogl_bitmap_get_size_from_file (const char *filename,
167 _COGL_RETURN_VAL_IF_FAIL (filename != NULL, FALSE);
169 if (gdk_pixbuf_get_file_info (filename, width, height) != NULL)
176 _cogl_bitmap_from_file (const char *filename,
179 static CoglUserDataKey pixbuf_key;
182 GdkColorspace color_space;
183 CoglPixelFormat pixel_format;
191 _COGL_GET_CONTEXT (ctx, NULL);
193 _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE);
195 /* Load from file using GdkPixbuf */
196 pixbuf = gdk_pixbuf_new_from_file (filename, error);
200 /* Get pixbuf properties */
201 has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
202 color_space = gdk_pixbuf_get_colorspace (pixbuf);
203 width = gdk_pixbuf_get_width (pixbuf);
204 height = gdk_pixbuf_get_height (pixbuf);
205 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
206 bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
207 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
209 /* According to current docs this should be true and so
210 * the translation to cogl pixel format below valid */
211 g_assert (bits_per_sample == 8);
214 g_assert (n_channels == 4);
216 g_assert (n_channels == 3);
218 /* Translate to cogl pixel format */
221 case GDK_COLORSPACE_RGB:
222 /* The only format supported by GdkPixbuf so far */
223 pixel_format = has_alpha ?
224 COGL_PIXEL_FORMAT_RGBA_8888 :
225 COGL_PIXEL_FORMAT_RGB_888;
229 /* Ouch, spec changed! */
230 g_object_unref (pixbuf);
234 /* We just use the data directly from the pixbuf so that we don't
235 have to copy to a seperate buffer. Note that Cogl is expected not
236 to read past the end of bpp*width on the last row even if the
237 rowstride is much larger so we don't need to worry about
238 GdkPixbuf's semantics that it may under-allocate the buffer. */
239 bmp = cogl_bitmap_new_for_data (ctx,
244 gdk_pixbuf_get_pixels (pixbuf));
246 cogl_object_set_user_data (COGL_OBJECT (bmp),
256 #include "stb_image.c"
259 _cogl_bitmap_get_size_from_file (const char *filename,
273 _cogl_bitmap_from_file (const char *filename,
276 static CoglUserDataKey bitmap_data_key;
278 int stb_pixel_format;
283 _COGL_GET_CONTEXT (ctx, NULL);
285 _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE);
287 /* Load from file using stb */
288 pixels = stbi_load (filename,
289 &width, &height, &stb_pixel_format,
294 /* Store bitmap info */
295 bmp = cogl_bitmap_new_for_data (ctx,
297 COGL_PIXEL_FORMAT_RGBA_8888,
298 width * 4, /* rowstride */
300 /* Register a destroy function so the pixel data will be freed
301 automatically when the bitmap object is destroyed */
302 cogl_object_set_user_data (COGL_OBJECT (bmp), &bitmap_data_key, pixels, free);