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.
19 #include "gdk-pixdata.h"
21 #include "gdk-pixbuf-private.h"
22 #include "gdk-pixbuf-i18n.h"
25 #define APPEND g_string_append_printf
27 /* --- functions --- */
29 pixdata_get_length (const GdkPixdata *pixdata)
33 if ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB)
35 else if ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA)
38 return 0; /* invalid format */
39 switch (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK)
43 case GDK_PIXDATA_ENCODING_RAW:
44 length = pixdata->rowstride * pixdata->height;
46 case GDK_PIXDATA_ENCODING_RLE:
47 /* need an RLE walk to determine size */
48 max_length = pixdata->rowstride * pixdata->height;
49 rle_buffer = pixdata->pixel_data;
51 while (length < max_length)
53 guint chunk_length = *(rle_buffer++);
55 if (chunk_length & 128)
57 chunk_length = chunk_length - 128;
58 if (!chunk_length) /* RLE data corrupted */
60 length += chunk_length * bpp;
65 if (!chunk_length) /* RLE data corrupted */
68 length += chunk_length;
69 rle_buffer += chunk_length;
72 length = rle_buffer - pixdata->pixel_data;
82 * gdk_pixdata_serialize:
83 * @pixdata: A valid GdkPixdata structure to serialize
84 * @stream_length_p: Location to store the resulting stream length in
86 * Serialize a #GdkPixdata structure into a byte stream.
87 * The byte stream consists of a straight forward write out of the
88 * #GdkPixdata fields in network byte order, plus the pixel_data
89 * bytes the structure points to.
91 * Return value: A newly-allocated string containing the serialized
92 * GdkPixdata structure
94 guint8* /* free result */
95 gdk_pixdata_serialize (const GdkPixdata *pixdata,
96 guint *stream_length_p)
102 /* check args passing */
103 g_return_val_if_fail (pixdata != NULL, NULL);
104 g_return_val_if_fail (stream_length_p != NULL, NULL);
105 /* check pixdata contents */
106 g_return_val_if_fail (pixdata->magic == GDK_PIXBUF_MAGIC_NUMBER, NULL);
107 g_return_val_if_fail (pixdata->width > 0, NULL);
108 g_return_val_if_fail (pixdata->height > 0, NULL);
109 g_return_val_if_fail (pixdata->rowstride >= pixdata->width, NULL);
110 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ||
111 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA, NULL);
112 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_SAMPLE_WIDTH_MASK) == GDK_PIXDATA_SAMPLE_WIDTH_8, NULL);
113 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RAW ||
114 (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RLE, NULL);
115 g_return_val_if_fail (pixdata->pixel_data != NULL, NULL);
117 length = pixdata_get_length (pixdata);
119 /* check length field */
120 g_return_val_if_fail (length != 0, NULL);
122 stream = g_malloc (GDK_PIXDATA_HEADER_LENGTH + length);
123 istream = (guint32*) stream;
126 *istream++ = g_htonl (GDK_PIXBUF_MAGIC_NUMBER);
127 *istream++ = g_htonl (GDK_PIXDATA_HEADER_LENGTH + length);
128 *istream++ = g_htonl (pixdata->pixdata_type);
129 *istream++ = g_htonl (pixdata->rowstride);
130 *istream++ = g_htonl (pixdata->width);
131 *istream++ = g_htonl (pixdata->height);
133 /* copy pixel data */
134 s = (guint8*) istream;
135 memcpy (s, pixdata->pixel_data, length);
138 *stream_length_p = GDK_PIXDATA_HEADER_LENGTH + length;
139 g_assert (s - stream == *stream_length_p); /* paranoid */
144 #define return_header_corrupt(error) { \
145 g_set_error (error, GDK_PIXBUF_ERROR, \
146 GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Image header corrupt")); \
149 #define return_invalid_format(error) { \
150 g_set_error (error, GDK_PIXBUF_ERROR, \
151 GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Image format unknown")); \
154 #define return_pixel_corrupt(error) { \
155 g_set_error (error, GDK_PIXBUF_ERROR, \
156 GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Image pixel data corrupt")); \
161 * gdk_pixdata_deserialize:
162 * @pixdata: A GdkPixdata structure to be filled in
163 * @stream_length: Length of the stream used for deserialization
164 * @stream: Stream of bytes containing a serialized pixdata structure
165 * @error: GError location to indicate failures (maybe NULL to ignore errors)
167 * Deserialize (reconstruct) a #GdkPixdata structure from a byte stream.
168 * The byte stream consists of a straight forward write out of the
169 * #GdkPixdata fields in network byte order, plus the pixel_data
170 * bytes the structure points to.
171 * The pixdata contents are reconstructed byte by byte and are checked
172 * for validity. This function may fail with %GDK_PIXBUF_CORRUPT_IMAGE
173 * or %GDK_PIXBUF_ERROR_UNKNOWN_TYPE
175 * Return value: Upon successfull deserialization %TRUE is returned,
179 gdk_pixdata_deserialize (GdkPixdata *pixdata,
181 const guint8 *stream,
185 guint color_type, sample_width, encoding;
187 g_return_val_if_fail (pixdata != NULL, FALSE);
188 if (stream_length < GDK_PIXDATA_HEADER_LENGTH)
189 return_header_corrupt (error);
190 g_return_val_if_fail (stream != NULL, FALSE);
193 /* deserialize header */
194 istream = (guint32*) stream;
196 * the deserialization of GdkPixdata will fail (at least on win32 with msvc 5.0)
197 * with 'g_ntohl(*istream++)' because the guint32 istream pointer is only
198 * incremented by 1 byte, if it is done within the g_ntohl() macro.
199 * Probably working around just another compiler bug ... --HB
201 pixdata->magic = g_ntohl (*istream); istream++;
202 pixdata->length = g_ntohl (*istream); istream++;
203 if (pixdata->magic != GDK_PIXBUF_MAGIC_NUMBER || pixdata->length < GDK_PIXDATA_HEADER_LENGTH)
204 return_header_corrupt (error);
205 pixdata->pixdata_type = g_ntohl (*istream); istream++;
206 pixdata->rowstride = g_ntohl (*istream); istream++;
207 pixdata->width = g_ntohl (*istream); istream++;
208 pixdata->height = g_ntohl (*istream); istream++;
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*) istream;
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);
294 gdk_pixdata_from_pixbuf (GdkPixdata *pixdata,
295 const GdkPixbuf *pixbuf,
298 gpointer free_me = NULL;
299 guint height, rowstride, encoding, bpp, length;
302 g_return_val_if_fail (pixdata != NULL, NULL);
303 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
304 g_return_val_if_fail (pixbuf->bits_per_sample == 8, NULL);
305 g_return_val_if_fail ((pixbuf->n_channels == 3 && !pixbuf->has_alpha) ||
306 (pixbuf->n_channels == 4 && pixbuf->has_alpha), NULL);
307 g_return_val_if_fail (pixbuf->rowstride >= pixbuf->width, NULL);
309 height = pixbuf->height;
310 rowstride = pixbuf->rowstride;
311 encoding = use_rle ? GDK_PIXDATA_ENCODING_RLE : GDK_PIXDATA_ENCODING_RAW;
312 bpp = pixbuf->has_alpha ? 4 : 3;
314 if (encoding == GDK_PIXDATA_ENCODING_RLE)
316 guint pad, n_bytes = rowstride * height;
317 guint8 *img_buffer_end, *data;
320 pad = MAX (pad, 130 + n_bytes / 127);
321 data = g_new (guint8, pad + n_bytes);
324 img_buffer_end = rl_encode_rgbx (img_buffer,
325 pixbuf->pixels, pixbuf->pixels + n_bytes,
327 length = img_buffer_end - img_buffer;
331 img_buffer = pixbuf->pixels;
332 length = rowstride * height;
335 pixdata->magic = GDK_PIXBUF_MAGIC_NUMBER;
336 pixdata->length = GDK_PIXDATA_HEADER_LENGTH + length;
337 pixdata->pixdata_type = pixbuf->has_alpha ? GDK_PIXDATA_COLOR_TYPE_RGBA : GDK_PIXDATA_COLOR_TYPE_RGB;
338 pixdata->pixdata_type |= GDK_PIXDATA_SAMPLE_WIDTH_8;
339 pixdata->pixdata_type |= encoding;
340 pixdata->rowstride = rowstride;
341 pixdata->width = pixbuf->width;
342 pixdata->height = height;
343 pixdata->pixel_data = img_buffer;
349 gdk_pixbuf_from_pixdata (const GdkPixdata *pixdata,
350 gboolean copy_pixels,
356 g_return_val_if_fail (pixdata != NULL, NULL);
357 g_return_val_if_fail (pixdata->width > 0, NULL);
358 g_return_val_if_fail (pixdata->height > 0, NULL);
359 g_return_val_if_fail (pixdata->rowstride >= pixdata->width, NULL);
360 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ||
361 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA, NULL);
362 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_SAMPLE_WIDTH_MASK) == GDK_PIXDATA_SAMPLE_WIDTH_8, NULL);
363 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RAW ||
364 (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RLE, NULL);
365 g_return_val_if_fail (pixdata->pixel_data != NULL, NULL);
367 bpp = (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ? 3 : 4;
368 encoding = pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK;
369 if (encoding == GDK_PIXDATA_ENCODING_RLE)
373 data = g_try_malloc (pixdata->rowstride * pixdata->height);
376 g_set_error (error, GDK_PIXBUF_ERROR,
377 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
378 _("failed to allocate image buffer of %u bytes"),
379 pixdata->rowstride * pixdata->height);
383 if (encoding == GDK_PIXDATA_ENCODING_RLE)
385 const guint8 *rle_buffer = pixdata->pixel_data;
386 guint8 *image_buffer = data;
387 guint8 *image_limit = data + pixdata->rowstride * pixdata->height;
388 gboolean check_overrun = FALSE;
390 while (image_buffer < image_limit)
392 guint length = *(rle_buffer++);
396 length = length - 128;
397 check_overrun = image_buffer + length * bpp > image_limit;
399 length = (image_limit - image_buffer) / bpp;
400 if (bpp < 4) /* RGB */
403 memcpy (image_buffer, rle_buffer, 3);
410 memcpy (image_buffer, rle_buffer, 4);
419 check_overrun = image_buffer + length > image_limit;
421 length = image_limit - image_buffer;
422 memcpy (image_buffer, rle_buffer, length);
423 image_buffer += length;
424 rle_buffer += length;
430 g_set_error (error, GDK_PIXBUF_ERROR,
431 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
432 _("Image pixel data corrupt"));
436 else if (copy_pixels)
437 memcpy (data, pixdata->pixel_data, pixdata->rowstride * pixdata->height);
439 data = pixdata->pixel_data;
441 return gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB,
442 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA,
443 8, pixdata->width, pixdata->height, pixdata->rowstride,
444 copy_pixels ? (GdkPixbufDestroyNotify) g_free : NULL, data);
449 gboolean dump_stream;
450 gboolean dump_struct;
451 gboolean dump_macros;
452 gboolean dump_gtypes;
453 gboolean dump_rle_decoder;
454 const gchar *static_prefix;
455 const gchar *const_prefix;
463 save_uchar (CSourceData *cdata,
466 GString *gstring = cdata->gstring;
470 if (cdata->dump_struct || cdata->dump_stream)
472 g_string_append (gstring, "\"\n \"");
476 if (cdata->dump_macros)
478 g_string_append (gstring, "\" \\\n \"");
483 if (d < 33 || d > 126)
485 APPEND (gstring, "\\%o", d);
486 cdata->pos += 1 + 1 + (d > 7) + (d > 63);
492 g_string_append (gstring, "\\\\");
497 g_string_append (gstring, "\\\"");
500 else if (cdata->pad && d >= '0' && d <= '9')
502 g_string_append (gstring, "\"\"");
503 g_string_append_c (gstring, d);
508 g_string_append_c (gstring, d);
516 save_rle_decoder (GString *gstring,
517 const gchar *macro_name,
519 const gchar *s_uint_8,
522 APPEND (gstring, "#define %s_RUN_LENGTH_DECODE(image_buf, rle_data, size, bpp) do \\\n",
524 APPEND (gstring, "{ %s __bpp; %s *__ip; const %s *__il, *__rd; \\\n", s_uint, s_uint_8, s_uint_8);
525 APPEND (gstring, " __bpp = (bpp); __ip = (image_buf); __il = __ip + (size) * __bpp; \\\n");
527 APPEND (gstring, " __rd = (rle_data); if (__bpp > 3) { /* RGBA */ \\\n");
529 APPEND (gstring, " while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
530 APPEND (gstring, " if (__l & 128) { __l = __l - 128; \\\n");
531 APPEND (gstring, " do { memcpy (__ip, __rd, 4); __ip += 4; } while (--__l); __rd += 4; \\\n");
532 APPEND (gstring, " } else { __l *= 4; memcpy (__ip, __rd, __l); \\\n");
533 APPEND (gstring, " __ip += __l; __rd += __l; } } \\\n");
535 APPEND (gstring, " } else { /* RGB */ \\\n");
537 APPEND (gstring, " while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
538 APPEND (gstring, " if (__l & 128) { __l = __l - 128; \\\n");
539 APPEND (gstring, " do { memcpy (__ip, __rd, 3); __ip += 3; } while (--__l); __rd += 3; \\\n");
540 APPEND (gstring, " } else { __l *= 3; memcpy (__ip, __rd, __l); \\\n");
541 APPEND (gstring, " __ip += __l; __rd += __l; } } \\\n");
543 APPEND (gstring, " } } while (0)\n");
547 gdk_pixdata_to_csource (GdkPixdata *pixdata,
549 GdkPixdataDumpType dump_type)
551 CSourceData cdata = { 0, };
552 gchar *s_uint_8, *s_uint_32, *s_uint, *s_char, *s_null;
553 guint bpp, width, height, rowstride;
554 gboolean rle_encoded;
556 guint8 *img_buffer, *img_buffer_end, *stream;
560 /* check args passing */
561 g_return_val_if_fail (pixdata != NULL, NULL);
562 g_return_val_if_fail (name != NULL, NULL);
563 /* check pixdata contents */
564 g_return_val_if_fail (pixdata->magic == GDK_PIXBUF_MAGIC_NUMBER, NULL);
565 g_return_val_if_fail (pixdata->width > 0, NULL);
566 g_return_val_if_fail (pixdata->height > 0, NULL);
567 g_return_val_if_fail (pixdata->rowstride >= pixdata->width, NULL);
568 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ||
569 (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGBA, NULL);
570 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_SAMPLE_WIDTH_MASK) == GDK_PIXDATA_SAMPLE_WIDTH_8, NULL);
571 g_return_val_if_fail ((pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RAW ||
572 (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_MASK) == GDK_PIXDATA_ENCODING_RLE, NULL);
573 g_return_val_if_fail (pixdata->pixel_data != NULL, NULL);
575 img_buffer = pixdata->pixel_data;
576 if (pixdata->length < 1)
577 img_buffer_end = img_buffer + pixdata_get_length (pixdata);
579 img_buffer_end = img_buffer + pixdata->length - GDK_PIXDATA_HEADER_LENGTH;
580 g_return_val_if_fail (img_buffer < img_buffer_end, NULL);
582 bpp = (pixdata->pixdata_type & GDK_PIXDATA_COLOR_TYPE_MASK) == GDK_PIXDATA_COLOR_TYPE_RGB ? 3 : 4;
583 width = pixdata->width;
584 height = pixdata->height;
585 rowstride = pixdata->rowstride;
586 rle_encoded = (pixdata->pixdata_type & GDK_PIXDATA_ENCODING_RLE) > 0;
587 macro_name = g_strdup (name);
588 g_strup (macro_name);
590 cdata.dump_macros = (dump_type & GDK_PIXDATA_DUMP_MACROS) > 0;
591 cdata.dump_struct = (dump_type & GDK_PIXDATA_DUMP_PIXDATA_STRUCT) > 0;
592 cdata.dump_stream = !cdata.dump_macros && !cdata.dump_struct;
593 g_return_val_if_fail (cdata.dump_macros + cdata.dump_struct + cdata.dump_stream == 1, NULL);
595 cdata.dump_gtypes = (dump_type & GDK_PIXDATA_DUMP_CTYPES) == 0;
596 cdata.dump_rle_decoder = (dump_type & GDK_PIXDATA_DUMP_RLE_DECODER) > 0;
597 cdata.static_prefix = (dump_type & GDK_PIXDATA_DUMP_STATIC) ? "static " : "";
598 cdata.const_prefix = (dump_type & GDK_PIXDATA_DUMP_CONST) ? "const " : "";
599 gstring = g_string_new ("");
600 cdata.gstring = gstring;
602 if (!cdata.dump_macros && cdata.dump_gtypes)
604 s_uint_8 = "guint8 ";
605 s_uint_32 = "guint32";
610 else if (!cdata.dump_macros)
612 s_uint_8 = "unsigned char";
613 s_uint_32 = "unsigned int ";
614 s_uint = "unsigned int ";
616 s_null = "(char*) 0";
618 else if (cdata.dump_macros && cdata.dump_gtypes)
621 s_uint_32 = "guint32";
626 else /* cdata.dump_macros && !cdata.dump_gtypes */
628 s_uint_8 = "unsigned char";
629 s_uint_32 = "unsigned int";
630 s_uint = "unsigned int";
632 s_null = "(char*) 0";
638 "/* GdkPixbuf %s C-Source image dump %s*/\n\n",
639 bpp > 3 ? "RGBA" : "RGB",
640 rle_encoded ? "1-byte-run-length-encoded " : "");
642 /* dump RLE decoder for structures
644 if (cdata.dump_rle_decoder && cdata.dump_struct)
645 save_rle_decoder (gstring,
647 cdata.dump_gtypes ? "guint" : "unsigned int",
648 cdata.dump_gtypes ? "guint8" : "unsigned char",
651 /* format & size blurbs
653 if (cdata.dump_macros)
655 APPEND (gstring, "#define %s_ROWSTRIDE (%u)\n",
656 macro_name, rowstride);
657 APPEND (gstring, "#define %s_WIDTH (%u)\n",
659 APPEND (gstring, "#define %s_HEIGHT (%u)\n",
661 APPEND (gstring, "#define %s_BYTES_PER_PIXEL (%u) /* 3:RGB, 4:RGBA */\n",
664 if (cdata.dump_struct)
666 APPEND (gstring, "%s%sGdkPixdata %s = {\n",
667 cdata.static_prefix, cdata.const_prefix, name);
668 APPEND (gstring, " 0x%x, /* Pixbuf magic: 'GdkP' */\n",
669 GDK_PIXBUF_MAGIC_NUMBER);
670 APPEND (gstring, " %u + %u, /* header length + pixel_data length */\n",
671 GDK_PIXDATA_HEADER_LENGTH,
672 rle_encoded ? img_buffer_end - img_buffer : rowstride * height);
673 APPEND (gstring, " 0x%x, /* pixdata_type */\n",
674 pixdata->pixdata_type);
675 APPEND (gstring, " %u, /* rowstride */\n",
677 APPEND (gstring, " %u, /* width */\n",
679 APPEND (gstring, " %u, /* height */\n",
681 APPEND (gstring, " /* pixel_data: */\n");
683 if (cdata.dump_stream)
685 guint pix_length = img_buffer_end - img_buffer;
687 stream = gdk_pixdata_serialize (pixdata, &stream_length);
688 img_buffer_end = stream + stream_length;
690 APPEND (gstring, "%s%s%s %s[] = \n",
691 cdata.static_prefix, cdata.const_prefix,
692 cdata.dump_gtypes ? "guint8" : "unsigned char",
694 APPEND (gstring, "( \"\"\n /* Pixbuf magic (0x%x) */\n \"",
695 GDK_PIXBUF_MAGIC_NUMBER);
697 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
698 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
699 APPEND (gstring, "\"\n /* length: header (%u) + pixel_data (%u) */\n \"",
700 GDK_PIXDATA_HEADER_LENGTH,
701 rle_encoded ? pix_length : rowstride * height);
703 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
704 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
705 APPEND (gstring, "\"\n /* pixdata_type (0x%x) */\n \"",
706 pixdata->pixdata_type);
708 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
709 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
710 APPEND (gstring, "\"\n /* rowstride (%u) */\n \"",
713 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
714 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
715 APPEND (gstring, "\"\n /* width (%u) */\n \"", width);
717 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
718 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
719 APPEND (gstring, "\"\n /* height (%u) */\n \"", height);
721 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
722 save_uchar (&cdata, *stream++); save_uchar (&cdata, *stream++);
723 APPEND (gstring, "\"\n /* pixel_data: */\n");
729 if (cdata.dump_macros)
731 APPEND (gstring, "#define %s_%sPIXEL_DATA ((%s*) \\\n",
733 rle_encoded ? "RLE_" : "",
735 APPEND (gstring, " \"");
738 if (cdata.dump_struct)
740 APPEND (gstring, " \"");
743 if (cdata.dump_stream)
745 APPEND (gstring, " \"");
752 save_uchar (&cdata, *img_buffer++);
753 while (img_buffer < img_buffer_end);
755 /* pixel_data trailer
757 if (cdata.dump_macros)
758 APPEND (gstring, "\")\n\n");
759 if (cdata.dump_struct)
760 APPEND (gstring, "\",\n};\n\n");
761 if (cdata.dump_stream)
762 APPEND (gstring, "\");\n\n");
764 /* dump RLE decoder for macros
766 if (cdata.dump_rle_decoder && cdata.dump_macros)
767 save_rle_decoder (gstring,
769 cdata.dump_gtypes ? "guint" : "unsigned int",
770 cdata.dump_gtypes ? "guint8" : "unsigned char",
781 * gdk_pixbuf_new_from_inline:
782 * @data_length: Length in bytes of the @data argument
783 * @data: Byte data containing a serialized GdkPixdata structure
784 * @copy_pixels: Whether to copy the pixel data, or use direct pointers
785 * @data for the resulting pixbuf
786 * @error: GError return location, may be %NULL to ignore errors
788 * Create a #GdkPixbuf from a flat representation that is suitable for
789 * storing as inline data in a program. This is useful if you want to
790 * ship a program with images, but don't want to depend on any
793 * Gtk+ ships with a program called gdk-pixbuf-csource which allowes
794 * for conversion of #GdkPixbufs into such a inline reprentation.
795 * In almost all cases, you should pass the --raw flag to
796 * gdk-pixbuf-csource. A sample invocation would be:
798 * gdk-pixbuf-csource --raw --name=myimage_inline myimage.png
800 * For the typical case where the inline pixbuf is read-only static data,
801 * you don't need to copy the pixel data unless you intend to write to
802 * it, so you can pass %FALSE for @copy_pixels. (If you pass --rle to
803 * gdk-pixbuf-csource, a copy will be made even if @copy_pixels is
804 * %FALSE, so using this option is generally a bad idea.)
806 * If you create a pixbuf from const inline data compiled into your
807 * program, it's probably safe to ignore errors, since things will
808 * always succeed. For non-const inline data, you could get out of
809 * memory. For untrusted inline data located at runtime, you could
810 * have corrupt inline data in addition.
812 * Return value: A newly-created #GdkPixbuf structure with a reference,
813 * count of 1, or %NULL if error is set.
816 gdk_pixbuf_new_from_inline (gint data_length,
818 gboolean copy_pixels,
823 if (data_length != -1)
824 g_return_val_if_fail (data_length > GDK_PIXDATA_HEADER_LENGTH, NULL);
825 g_return_val_if_fail (data != NULL, NULL);
827 if (!gdk_pixdata_deserialize (&pixdata, data_length, data, error))
830 return gdk_pixbuf_from_pixdata (&pixdata, copy_pixels, error);