1 /* GdkPixbuf library - GdkPixdata - functions for inlined pixbuf handling
2 * Copyright (C) 1999, 2001 Tim Janik
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include "gdk-pixbuf-private.h"
22 #include "gdk-pixdata.h"
23 #include "gdk-pixbuf-alias.h"
26 #define APPEND g_string_append_printf
28 /* --- functions --- */
30 pixdata_get_length (const GdkPixdata *pixdata)
34 if ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB)
36 else if ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA)
39 return 0; /* invalid format */
40 switch (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK)
44 case GDK_PIXDATA_ENCODING_RAW:
45 length = pixdata->rowstride * pixdata->height;
47 case GDK_PIXDATA_ENCODING_RLE:
48 /* need an RLE walk to determine size */
49 max_length = pixdata->rowstride * pixdata->height;
50 rle_buffer = pixdata->pixel_data;
52 while (length < max_length)
54 guint chunk_length = *(rle_buffer++);
56 if (chunk_length & 128)
58 chunk_length = chunk_length - 128;
59 if (!chunk_length) /* RLE data corrupted */
61 length += chunk_length * bpp;
66 if (!chunk_length) /* RLE data corrupted */
69 length += chunk_length;
70 rle_buffer += chunk_length;
73 length = rle_buffer - pixdata->pixel_data;
83 * gdk_pixdata_serialize:
84 * @pixdata: a valid #GdkPixdata structure to serialize.
85 * @stream_length_p: location to store the resulting stream length in.
87 * Serializes a #GdkPixdata structure into a byte stream.
88 * The byte stream consists of a straightforward writeout of the
89 * #GdkPixdata fields in network byte order, plus the @pixel_data
90 * bytes the structure points to.
92 * Return value: A newly-allocated string containing the serialized
93 * #GdkPixdata structure.
95 guint8* /* free result */
96 gdk_pixdata_serialize (const GdkPixdata *pixdata,
97 guint *stream_length_p)
103 /* check args passing */
104 g_return_val_if_fail (pixdata != NULL, NULL);
105 g_return_val_if_fail (stream_length_p != NULL, NULL);
106 /* check pixdata contents */
107 g_return_val_if_fail (pixdata->magic == GDK_PIXBUF_MAGIC_NUMBER, NULL);
108 g_return_val_if_fail (pixdata->width > 0, NULL);
109 g_return_val_if_fail (pixdata->height > 0, NULL);
110 g_return_val_if_fail (pixdata->rowstride >= pixdata->width, NULL);
111 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ||
112 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA, NULL);
113 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_SAMPLE_WIDTH_MASK) == GDK_PIXDATA_SAMPLE_WIDTH_8, NULL);
114 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RAW ||
115 (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RLE, NULL);
116 g_return_val_if_fail (pixdata->pixel_data != NULL, NULL);
118 length = pixdata_get_length (pixdata);
120 /* check length field */
121 g_return_val_if_fail (length != 0, NULL);
123 stream = g_malloc (GDK_PIXDATA_HEADER_LENGTH + length);
124 istream = (guint32*) stream;
127 *istream++ = g_htonl (GDK_PIXBUF_MAGIC_NUMBER);
128 *istream++ = g_htonl (GDK_PIXDATA_HEADER_LENGTH + length);
129 *istream++ = g_htonl (pixdata->pixdata_type);
130 *istream++ = g_htonl (pixdata->rowstride);
131 *istream++ = g_htonl (pixdata->width);
132 *istream++ = g_htonl (pixdata->height);
134 /* copy pixel data */
135 s = (guint8*) istream;
136 memcpy (s, pixdata->pixel_data, length);
139 *stream_length_p = GDK_PIXDATA_HEADER_LENGTH + length;
140 g_assert (s - stream == *stream_length_p); /* paranoid */
145 #define return_header_corrupt(error) { \
146 g_set_error (error, GDK_PIXBUF_ERROR, \
147 GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Image header corrupt")); \
150 #define return_invalid_format(error) { \
151 g_set_error (error, GDK_PIXBUF_ERROR, \
152 GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Image format unknown")); \
155 #define return_pixel_corrupt(error) { \
156 g_set_error (error, GDK_PIXBUF_ERROR, \
157 GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Image pixel data corrupt")); \
161 static inline const guint8 *
162 get_uint32 (const guint8 *stream, guint *result)
164 *result = (stream[0] << 24) + (stream[1] << 16) + (stream[2] << 8) + stream[3];
169 * gdk_pixdata_deserialize:
170 * @pixdata: a #GdkPixdata structure to be filled in.
171 * @stream_length: length of the stream used for deserialization.
172 * @stream: stream of bytes containing a serialized #GdkPixdata structure.
173 * @error: #GError location to indicate failures (maybe %NULL to ignore errors).
175 * Deserializes (reconstruct) a #GdkPixdata structure from a byte stream.
176 * The byte stream consists of a straightforward writeout of the
177 * #GdkPixdata fields in network byte order, plus the @pixel_data
178 * bytes the structure points to.
179 * The @pixdata contents are reconstructed byte by byte and are checked
180 * for validity. This function may fail with %GDK_PIXBUF_CORRUPT_IMAGE
181 * or %GDK_PIXBUF_ERROR_UNKNOWN_TYPE.
183 * Return value: Upon successful deserialization %TRUE is returned,
187 gdk_pixdata_deserialize (GdkPixdata *pixdata,
189 const guint8 *stream,
192 guint color_type, sample_width, encoding;
194 g_return_val_if_fail (pixdata != NULL, FALSE);
195 if (stream_length < GDK_PIXDATA_HEADER_LENGTH)
196 return_header_corrupt (error);
197 g_return_val_if_fail (stream != NULL, FALSE);
200 /* deserialize header */
201 stream = get_uint32 (stream, &pixdata->magic);
202 stream = get_uint32 (stream, (guint32 *)&pixdata->length);
203 if (pixdata->magic != GDK_PIXBUF_MAGIC_NUMBER || pixdata->length < GDK_PIXDATA_HEADER_LENGTH)
204 return_header_corrupt (error);
205 stream = get_uint32 (stream, &pixdata->pixdata_type);
206 stream = get_uint32 (stream, &pixdata->rowstride);
207 stream = get_uint32 (stream, &pixdata->width);
208 stream = get_uint32 (stream, &pixdata->height);
209 if (pixdata->width < 1 || pixdata->height < 1 ||
210 pixdata->rowstride < pixdata->width)
211 return_header_corrupt (error);
212 color_type = pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK;
213 sample_width = pixdata->pixdata_type & GDK_PIXDATA_SAMPLE_WIDTH_MASK;
214 encoding = pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK;
215 if ((color_type != GDK_PIXDATA_COLOR_TYPE_RGB &&
216 color_type != GDK_PIXDATA_COLOR_TYPE_RGBA) ||
217 sample_width != GDK_PIXDATA_SAMPLE_WIDTH_8 ||
218 (encoding != GDK_PIXDATA_ENCODING_RAW &&
219 encoding != GDK_PIXDATA_ENCODING_RLE))
220 return_invalid_format (error);
222 /* deserialize pixel data */
223 if (stream_length < pixdata->length - GDK_PIXDATA_HEADER_LENGTH)
224 return_pixel_corrupt (error);
225 pixdata->pixel_data = (guint8 *)stream;
231 diff2_rgb (guint8 *ip)
233 return ip[0] != ip[3] || ip[1] != ip[4] || ip[2] != ip[5];
237 diff2_rgba (guint8 *ip)
239 return ip[0] != ip[4] || ip[1] != ip[5] || ip[2] != ip[6] || ip[3] != ip[7];
242 static guint8* /* dest buffer bound */
243 rl_encode_rgbx (guint8 *bp, /* dest buffer */
244 guint8 *ip, /* image pointer */
245 guint8 *limit, /* image upper bound */
248 gboolean (*diff2_pix) (guint8 *) = n_ch > 3 ? diff2_rgba : diff2_rgb;
249 guint8 *ilimit = limit - n_ch;
253 g_assert (ip < ilimit); /* paranoid */
261 while (l < 127 && ip < ilimit && diff2_pix (ip))
262 { ip += n_ch; l += 1; }
263 if (ip == ilimit && l < 127)
264 { ip += n_ch; l += 1; }
266 memcpy (bp, s_ip, l * n_ch);
274 while (l < 127 && ip < ilimit && !diff2_pix (ip))
275 { ip += n_ch; l += 1; }
277 memcpy (bp, ip, n_ch);
284 memcpy (bp, ip, n_ch);
293 /* Used as the destroy notification function for gdk_pixbuf_new() */
295 free_buffer (guchar *pixels, gpointer data)
301 * gdk_pixdata_from_pixbuf:
302 * @pixdata: a #GdkPixdata to fill.
303 * @pixbuf: the data to fill @pixdata with.
304 * @use_rle: whether to use run-length encoding for the pixel data.
306 * Converts a #GdkPixbuf to a #GdkPixdata. If @use_rle is %TRUE, the
307 * pixel data is run-length encoded into newly-allocated memory and a
308 * pointer to that memory is returned.
310 * Returns: If @ure_rle is %TRUE, a pointer to the newly-allocated memory
311 * for the run-length encoded pixel data, otherwise %NULL.
314 gdk_pixdata_from_pixbuf (GdkPixdata *pixdata,
315 const GdkPixbuf *pixbuf,
318 gpointer free_me = NULL;
319 guint height, rowstride, encoding, bpp, length;
322 g_return_val_if_fail (pixdata != NULL, NULL);
323 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
324 g_return_val_if_fail (pixbuf->bits_per_sample == 8, NULL);
325 g_return_val_if_fail ((pixbuf->n_channels == 3 && !pixbuf->has_alpha) ||
326 (pixbuf->n_channels == 4 && pixbuf->has_alpha), NULL);
327 g_return_val_if_fail (pixbuf->rowstride >= pixbuf->width, NULL);
329 height = pixbuf->height;
330 rowstride = pixbuf->rowstride;
331 encoding = use_rle ? GDK_PIXDATA_ENCODING_RLE : GDK_PIXDATA_ENCODING_RAW;
332 bpp = pixbuf->has_alpha ? 4 : 3;
334 if (encoding == GDK_PIXDATA_ENCODING_RLE)
336 guint pad, n_bytes = rowstride * height;
337 guint8 *img_buffer_end, *data;
338 GdkPixbuf *buf = NULL;
340 if (n_bytes % bpp != 0)
342 rowstride = pixbuf->width * bpp;
343 n_bytes = rowstride * height;
344 data = g_malloc (n_bytes);
345 buf = gdk_pixbuf_new_from_data (data,
347 pixbuf->has_alpha, 8,
352 gdk_pixbuf_copy_area (pixbuf, 0, 0, pixbuf->width, pixbuf->height,
356 buf = (GdkPixbuf *)pixbuf;
358 pad = MAX (pad, 130 + n_bytes / 127);
359 data = g_new (guint8, pad + n_bytes);
362 img_buffer_end = rl_encode_rgbx (img_buffer,
363 buf->pixels, buf->pixels + n_bytes,
365 length = img_buffer_end - img_buffer;
367 g_object_unref (buf);
371 img_buffer = pixbuf->pixels;
372 length = rowstride * height;
375 pixdata->magic = GDK_PIXBUF_MAGIC_NUMBER;
376 pixdata->length = GDK_PIXDATA_HEADER_LENGTH + length;
377 pixdata->pixdata_type = pixbuf->has_alpha ? GDK_PIXDATA_COLOR_TYPE_RGBA : GDK_PIXDATA_COLOR_TYPE_RGB;
378 pixdata->pixdata_type |= GDK_PIXDATA_SAMPLE_WIDTH_8;
379 pixdata->pixdata_type |= encoding;
380 pixdata->rowstride = rowstride;
381 pixdata->width = pixbuf->width;
382 pixdata->height = height;
383 pixdata->pixel_data = img_buffer;
389 * gdk_pixbuf_from_pixdata:
390 * @pixdata: a #GdkPixdata to convert into a #GdkPixbuf.
391 * @copy_pixels: whether to copy raw pixel data; run-length encoded
392 * pixel data is always copied.
393 * @error: location to store possible errors.
395 * Converts a #GdkPixdata to a #GdkPixbuf. If @copy_pixels is %TRUE or
396 * if the pixel data is run-length-encoded, the pixel data is copied into
397 * newly-allocated memory; otherwise it is reused.
399 * Returns: a new #GdkPixbuf.
402 gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
403 gboolean copy_pixels,
409 g_return_val_if_fail (pixdata != NULL, NULL);
410 g_return_val_if_fail (pixdata->width > 0, NULL);
411 g_return_val_if_fail (pixdata->height > 0, NULL);
412 g_return_val_if_fail (pixdata->rowstride >= pixdata->width, NULL);
413 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ||
414 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA, NULL);
415 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_SAMPLE_WIDTH_MASK) == GDK_PIXDATA_SAMPLE_WIDTH_8, NULL);
416 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RAW ||
417 (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RLE, NULL);
418 g_return_val_if_fail (pixdata->pixel_data != NULL, NULL);
420 bpp = (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ? 3 : 4;
421 encoding = pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK;
422 if (encoding == GDK_PIXDATA_ENCODING_RLE)
426 data = g_try_malloc (pixdata->rowstride * pixdata->height);
429 g_set_error (error, GDK_PIXBUF_ERROR,
430 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
431 ngettext("failed to allocate image buffer of %u byte",
432 "failed to allocate image buffer of %u bytes",
433 pixdata->rowstride * pixdata->height),
434 pixdata->rowstride * pixdata->height);
438 if (encoding == GDK_PIXDATA_ENCODING_RLE)
440 const guint8 *rle_buffer = pixdata->pixel_data;
441 guint8 *image_buffer = data;
442 guint8 *image_limit = data + pixdata->rowstride * pixdata->height;
443 gboolean check_overrun = FALSE;
445 while (image_buffer < image_limit)
447 guint length = *(rle_buffer++);
451 length = length - 128;
452 check_overrun = image_buffer + length * bpp > image_limit;
454 length = (image_limit - image_buffer) / bpp;
455 if (bpp < 4) /* RGB */
458 memcpy (image_buffer, rle_buffer, 3);
465 memcpy (image_buffer, rle_buffer, 4);
474 check_overrun = image_buffer + length > image_limit;
476 length = image_limit - image_buffer;
477 memcpy (image_buffer, rle_buffer, length);
478 image_buffer += length;
479 rle_buffer += length;
485 g_set_error (error, GDK_PIXBUF_ERROR,
486 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
487 _("Image pixel data corrupt"));
491 else if (copy_pixels)
492 memcpy (data, pixdata->pixel_data, pixdata->rowstride * pixdata->height);
494 data = pixdata->pixel_data;
496 return gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB,
497 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA,
498 8, pixdata->width, pixdata->height, pixdata->rowstride,
499 copy_pixels ? (GdkPixbufDestroyNotify) g_free : NULL, data);
504 gboolean dump_stream;
505 gboolean dump_struct;
506 gboolean dump_macros;
507 gboolean dump_gtypes;
508 gboolean dump_rle_decoder;
509 const gchar *static_prefix;
510 const gchar *const_prefix;
518 save_uchar (CSourceData *cdata,
521 GString *gstring = cdata->gstring;
525 if (cdata->dump_struct || cdata->dump_stream)
527 g_string_append (gstring, "\"\n \"");
531 if (cdata->dump_macros)
533 g_string_append (gstring, "\" \\\n \"");
538 if (d < 33 || d > 126 || d == '?')
540 APPEND (gstring, "\\%o", d);
541 cdata->pos += 1 + 1 + (d > 7) + (d > 63);
547 g_string_append (gstring, "\\\\");
552 g_string_append (gstring, "\\\"");
555 else if (cdata->pad && d >= '0' && d <= '9')
557 g_string_append (gstring, "\"\"");
558 g_string_append_c (gstring, d);
563 g_string_append_c (gstring, d);
571 save_rle_decoder (GString *gstring,
572 const gchar *macro_name,
574 const gchar *s_uint_8,
577 APPEND (gstring, "#define %s_RUN_LENGTH_DECODE(image_buf, rle_data, size, bpp) do \\\n",
579 APPEND (gstring, "{ %s __bpp; %s *__ip; const %s *__il, *__rd; \\\n", s_uint, s_uint_8, s_uint_8);
580 APPEND (gstring, " __bpp = (bpp); __ip = (image_buf); __il = __ip + (size) * __bpp; \\\n");
582 APPEND (gstring, " __rd = (rle_data); if (__bpp > 3) { /* RGBA */ \\\n");
584 APPEND (gstring, " while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
585 APPEND (gstring, " if (__l & 128) { __l = __l - 128; \\\n");
586 APPEND (gstring, " do { memcpy (__ip, __rd, 4); __ip += 4; } while (--__l); __rd += 4; \\\n");
587 APPEND (gstring, " } else { __l *= 4; memcpy (__ip, __rd, __l); \\\n");
588 APPEND (gstring, " __ip += __l; __rd += __l; } } \\\n");
590 APPEND (gstring, " } else { /* RGB */ \\\n");
592 APPEND (gstring, " while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
593 APPEND (gstring, " if (__l & 128) { __l = __l - 128; \\\n");
594 APPEND (gstring, " do { memcpy (__ip, __rd, 3); __ip += 3; } while (--__l); __rd += 3; \\\n");
595 APPEND (gstring, " } else { __l *= 3; memcpy (__ip, __rd, __l); \\\n");
596 APPEND (gstring, " __ip += __l; __rd += __l; } } \\\n");
598 APPEND (gstring, " } } while (0)\n");
602 * gdk_pixdata_to_csource:
603 * @pixdata: a #GdkPixdata to convert to C source.
604 * @name: used for naming generated data structures or macros.
605 * @dump_type: a #GdkPixdataDumpType determining the kind of C
606 * source to be generated.
608 * Generates C source code suitable for compiling images directly
611 * GTK+ ships with a program called <command>gdk-pixbuf-csource</command>
612 * which offers a command line interface to this function.
614 * Returns: a newly-allocated string containing the C source form
618 gdk_pixdata_to_csource (GdkPixdata *pixdata,
620 GdkPixdataDumpType dump_type)
622 CSourceData cdata = { 0, };
623 gchar *s_uint_8, *s_uint_32, *s_uint, *s_char, *s_null;
624 guint bpp, width, height, rowstride;
625 gboolean rle_encoded;
627 guint8 *img_buffer, *img_buffer_end, *stream = NULL;
631 /* check args passing */
632 g_return_val_if_fail (pixdata != NULL, NULL);
633 g_return_val_if_fail (name != NULL, NULL);
634 /* check pixdata contents */
635 g_return_val_if_fail (pixdata->magic == GDK_PIXBUF_MAGIC_NUMBER, NULL);
636 g_return_val_if_fail (pixdata->width > 0, NULL);
637 g_return_val_if_fail (pixdata->height > 0, NULL);
638 g_return_val_if_fail (pixdata->rowstride >= pixdata->width, NULL);
639 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ||
640 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA, NULL);
641 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_SAMPLE_WIDTH_MASK) == GDK_PIXDATA_SAMPLE_WIDTH_8, NULL);
642 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RAW ||
643 (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RLE, NULL);
644 g_return_val_if_fail (pixdata->pixel_data != NULL, NULL);
646 img_buffer = pixdata->pixel_data;
647 if (pixdata->length < 1)
648 img_buffer_end = img_buffer + pixdata_get_length (pixdata);
650 img_buffer_end = img_buffer + pixdata->length - GDK_PIXDATA_HEADER_LENGTH;
651 g_return_val_if_fail (img_buffer < img_buffer_end, NULL);
653 bpp = (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ? 3 : 4;
654 width = pixdata->width;
655 height = pixdata->height;
656 rowstride = pixdata->rowstride;
657 rle_encoded = (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_RLE) > 0;
658 macro_name = g_ascii_strup (name, -1);
660 cdata.dump_macros = (dump_type & GDK_PIXDATA_DUMP_MACROS) > 0;
661 cdata.dump_struct = (dump_type & GDK_PIXDATA_DUMP_PIXDATA_STRUCT) > 0;
662 cdata.dump_stream = !cdata.dump_macros && !cdata.dump_struct;
663 g_return_val_if_fail (cdata.dump_macros + cdata.dump_struct + cdata.dump_stream == 1, NULL);
665 cdata.dump_gtypes = (dump_type & GDK_PIXDATA_DUMP_CTYPES) == 0;
666 cdata.dump_rle_decoder = (dump_type & GDK_PIXDATA_DUMP_RLE_DECODER) > 0;
667 cdata.static_prefix = (dump_type & GDK_PIXDATA_DUMP_STATIC) ? "static " : "";
668 cdata.const_prefix = (dump_type & GDK_PIXDATA_DUMP_CONST) ? "const " : "";
669 gstring = g_string_new (NULL);
670 cdata.gstring = gstring;
672 if (!cdata.dump_macros && cdata.dump_gtypes)
674 s_uint_8 = "guint8 ";
675 s_uint_32 = "guint32";
680 else if (!cdata.dump_macros)
682 s_uint_8 = "unsigned char";
683 s_uint_32 = "unsigned int ";
684 s_uint = "unsigned int ";
686 s_null = "(char*) 0";
688 else if (cdata.dump_macros && cdata.dump_gtypes)
691 s_uint_32 = "guint32";
696 else /* cdata.dump_macros && !cdata.dump_gtypes */
698 s_uint_8 = "unsigned char";
699 s_uint_32 = "unsigned int";
700 s_uint = "unsigned int";
702 s_null = "(char*) 0";
708 "/* GdkPixbuf %s C-Source image dump %s*/\n\n",
709 bpp > 3 ? "RGBA" : "RGB",
710 rle_encoded ? "1-byte-run-length-encoded " : "");
712 /* dump RLE decoder for structures
714 if (cdata.dump_rle_decoder && cdata.dump_struct)
715 save_rle_decoder (gstring,
717 cdata.dump_gtypes ? "guint" : "unsigned int",
718 cdata.dump_gtypes ? "guint8" : "unsigned char",
721 /* format & size blurbs
723 if (cdata.dump_macros)
725 APPEND (gstring, "#define %s_ROWSTRIDE (%u)\n",
726 macro_name, rowstride);
727 APPEND (gstring, "#define %s_WIDTH (%u)\n",
729 APPEND (gstring, "#define %s_HEIGHT (%u)\n",
731 APPEND (gstring, "#define %s_BYTES_PER_PIXEL (%u) /* 3:RGB, 4:RGBA */\n",
734 if (cdata.dump_struct)
736 APPEND (gstring, "%s%sGdkPixdata %s = {\n",
737 cdata.static_prefix, cdata.const_prefix, name);
738 APPEND (gstring, " 0x%x, /* Pixbuf magic: 'GdkP' */\n",
739 GDK_PIXBUF_MAGIC_NUMBER);
740 APPEND (gstring, " %d + %lu, /* header length + pixel_data length */\n",
741 GDK_PIXDATA_HEADER_LENGTH,
742 rle_encoded ? (glong)(img_buffer_end - img_buffer) : (glong)rowstride * height);
743 APPEND (gstring, " 0x%x, /* pixdata_type */\n",
744 pixdata->pixdata_type);
745 APPEND (gstring, " %u, /* rowstride */\n",
747 APPEND (gstring, " %u, /* width */\n",
749 APPEND (gstring, " %u, /* height */\n",
751 APPEND (gstring, " /* pixel_data: */\n");
753 if (cdata.dump_stream)
755 guint pix_length = img_buffer_end - img_buffer;
757 stream = gdk_pixdata_serialize (pixdata, &stream_length);
759 img_buffer_end = stream + stream_length;
761 APPEND (gstring, "#ifdef __SUNPRO_C\n");
762 APPEND (gstring, "#pragma align 4 (%s)\n", name);
763 APPEND (gstring, "#endif\n");
765 APPEND (gstring, "#ifdef __GNUC__\n");
766 APPEND (gstring, "%s%s%s %s[] __attribute__ ((__aligned__ (4))) = \n",
767 cdata.static_prefix, cdata.const_prefix,
768 cdata.dump_gtypes ? "guint8" : "unsigned char",
770 APPEND (gstring, "#else\n");
771 APPEND (gstring, "%s%s%s %s[] = \n",
772 cdata.static_prefix, cdata.const_prefix,
773 cdata.dump_gtypes ? "guint8" : "unsigned char",
775 APPEND (gstring, "#endif\n");
777 APPEND (gstring, "{ \"\"\n /* Pixbuf magic (0x%x) */\n \"",
778 GDK_PIXBUF_MAGIC_NUMBER);
780 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
781 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
782 APPEND (gstring, "\"\n /* length: header (%d) + pixel_data (%u) */\n \"",
783 GDK_PIXDATA_HEADER_LENGTH,
784 rle_encoded ? pix_length : rowstride * height);
786 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
787 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
788 APPEND (gstring, "\"\n /* pixdata_type (0x%x) */\n \"",
789 pixdata->pixdata_type);
791 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
792 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
793 APPEND (gstring, "\"\n /* rowstride (%u) */\n \"",
796 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
797 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
798 APPEND (gstring, "\"\n /* width (%u) */\n \"", width);
800 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
801 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
802 APPEND (gstring, "\"\n /* height (%u) */\n \"", height);
804 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
805 save_uchar (&cdata, *img_buffer++); save_uchar (&cdata, *img_buffer++);
806 APPEND (gstring, "\"\n /* pixel_data: */\n");
811 if (cdata.dump_macros)
813 APPEND (gstring, "#define %s_%sPIXEL_DATA ((%s*) \\\n",
815 rle_encoded ? "RLE_" : "",
817 APPEND (gstring, " \"");
820 if (cdata.dump_struct)
822 APPEND (gstring, " \"");
825 if (cdata.dump_stream)
827 APPEND (gstring, " \"");
834 save_uchar (&cdata, *img_buffer++);
835 while (img_buffer < img_buffer_end);
837 /* pixel_data trailer
839 if (cdata.dump_macros)
840 APPEND (gstring, "\")\n\n");
841 if (cdata.dump_struct)
842 APPEND (gstring, "\",\n};\n\n");
843 if (cdata.dump_stream)
844 APPEND (gstring, "\"};\n\n");
846 /* dump RLE decoder for macros
848 if (cdata.dump_rle_decoder && cdata.dump_macros)
849 save_rle_decoder (gstring,
851 cdata.dump_gtypes ? "guint" : "unsigned int",
852 cdata.dump_gtypes ? "guint8" : "unsigned char",
864 * gdk_pixbuf_new_from_inline:
865 * @data_length: Length in bytes of the @data argument or -1 to
866 * disable length checks
867 * @data: Byte data containing a serialized #GdkPixdata structure
868 * @copy_pixels: Whether to copy the pixel data, or use direct pointers
869 * @data for the resulting pixbuf
870 * @error: #GError return location, may be %NULL to ignore errors
872 * Create a #GdkPixbuf from a flat representation that is suitable for
873 * storing as inline data in a program. This is useful if you want to
874 * ship a program with images, but don't want to depend on any
877 * GTK+ ships with a program called <command>gdk-pixbuf-csource</command>
878 * which allows for conversion of #GdkPixbufs into such a inline representation.
879 * In almost all cases, you should pass the <option>--raw</option> flag to
880 * <command>gdk-pixbuf-csource</command>. A sample invocation would be:
882 * <informalexample><programlisting>
883 * gdk-pixbuf-csource --raw --name=myimage_inline myimage.png
884 * </programlisting></informalexample>
886 * For the typical case where the inline pixbuf is read-only static data,
887 * you don't need to copy the pixel data unless you intend to write to
888 * it, so you can pass %FALSE for @copy_pixels. (If you pass
889 * <option>--rle</option> to <command>gdk-pixbuf-csource</command>, a copy
890 * will be made even if @copy_pixels is %FALSE, so using this option is
891 * generally a bad idea.)
893 * If you create a pixbuf from const inline data compiled into your
894 * program, it's probably safe to ignore errors and disable length checks,
895 * since things will always succeed:
896 * <informalexample><programlisting>
897 * pixbuf = gdk_pixbuf_new_from_inline (-1, myimage_inline, FALSE, NULL);
898 * </programlisting></informalexample>
900 * For non-const inline data, you could get out of memory. For untrusted
901 * inline data located at runtime, you could have corrupt inline data in
904 * Return value: A newly-created #GdkPixbuf structure with a reference,
905 * count of 1, or %NULL if an error occurred.
908 gdk_pixbuf_new_from_inline (gint data_length,
910 gboolean copy_pixels,
915 if (data_length != -1)
916 g_return_val_if_fail (data_length > GDK_PIXDATA_HEADER_LENGTH, NULL);
917 g_return_val_if_fail (data != NULL, NULL);
919 if (!gdk_pixdata_deserialize (&pixdata, data_length, data, error))
922 return gdk_pixbuf_from_pixdata (&pixdata, copy_pixels, error);
925 #define __GDK_PIXDATA_C__
926 #include "gdk-pixbuf-aliasdef.c"