]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/gdk-pixbuf-io.c
Updated Czech translation.
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-io.c
1 /* -*- mode: C; c-file-style: "linux" -*- */
2 /* GdkPixbuf library - Main loading interface.
3  *
4  * Copyright (C) 1999 The Free Software Foundation
5  *
6  * Authors: Miguel de Icaza <miguel@gnu.org>
7  *          Federico Mena-Quintero <federico@gimp.org>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #include <glib.h>
36 #include <gio/gio.h>
37
38 #include "gdk-pixbuf-private.h"
39 #include "gdk-pixbuf-io.h"
40 #include "gdk-pixbuf-loader.h"
41 #include "gdk-pixbuf-alias.h"
42
43 #include <glib/gstdio.h>
44
45 #ifdef G_OS_WIN32
46 #define STRICT
47 #include <windows.h>
48 #undef STRICT
49 #endif
50
51 #define SNIFF_BUFFER_SIZE 4096
52 #define LOAD_BUFFER_SIZE 65536
53
54 #ifndef GDK_PIXBUF_USE_GIO_MIME 
55 static gint 
56 format_check (GdkPixbufModule *module, guchar *buffer, int size)
57 {
58         int i, j;
59         gchar m;
60         GdkPixbufModulePattern *pattern;
61         gboolean anchored;
62         guchar *prefix;
63         gchar *mask;
64
65         for (pattern = module->info->signature; pattern->prefix; pattern++) {
66                 if (pattern->mask && pattern->mask[0] == '*') {
67                         prefix = (guchar *)pattern->prefix + 1;
68                         mask = pattern->mask + 1;
69                         anchored = FALSE;
70                 }
71                 else {
72                         prefix = (guchar *)pattern->prefix;
73                         mask = pattern->mask;
74                         anchored = TRUE;
75                 }
76                 for (i = 0; i < size; i++) {
77                         for (j = 0; i + j < size && prefix[j] != 0; j++) {
78                                 m = mask ? mask[j] : ' ';
79                                 if (m == ' ') {
80                                         if (buffer[i + j] != prefix[j])
81                                                 break;
82                                 }
83                                 else if (m == '!') {
84                                         if (buffer[i + j] == prefix[j])
85                                                 break;
86                                 }
87                                 else if (m == 'z') {
88                                         if (buffer[i + j] != 0)
89                                                 break;
90                                 }
91                                 else if (m == 'n') {
92                                         if (buffer[i + j] == 0)
93                                                 break;
94                                 }
95                         } 
96
97                         if (prefix[j] == 0) 
98                                 return pattern->relevance;
99
100                         if (anchored)
101                                 break;
102                 }
103         }
104         return 0;
105 }
106 #endif
107
108 G_LOCK_DEFINE_STATIC (init_lock);
109 G_LOCK_DEFINE_STATIC (threadunsafe_loader_lock);
110
111 gboolean
112 _gdk_pixbuf_lock (GdkPixbufModule *image_module)
113 {
114         if (g_threads_got_initialized &&
115             !(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) {
116                 G_LOCK (threadunsafe_loader_lock);
117
118                 return TRUE;
119         }
120
121         return FALSE;
122 }
123  
124 void
125 _gdk_pixbuf_unlock (GdkPixbufModule *image_module)
126 {
127         if (!(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) {
128                 G_UNLOCK (threadunsafe_loader_lock);
129         }
130 }
131
132 static GSList *file_formats = NULL;
133
134 static void gdk_pixbuf_io_init (void);
135
136 static GSList *
137 get_file_formats (void)
138 {
139         G_LOCK (init_lock);
140         if (file_formats == NULL)
141                 gdk_pixbuf_io_init ();
142         G_UNLOCK (init_lock);
143         
144         return file_formats;
145 }
146
147
148 #ifdef USE_GMODULE 
149
150 static gboolean
151 scan_string (const char **pos, GString *out)
152 {
153         const char *p = *pos, *q = *pos;
154         char *tmp, *tmp2;
155         gboolean quoted;
156         
157         while (g_ascii_isspace (*p))
158                 p++;
159         
160         if (!*p)
161                 return FALSE;
162         else if (*p == '"') {
163                 p++;
164                 quoted = FALSE;
165                 for (q = p; (*q != '"') || quoted; q++) {
166                         if (!*q)
167                                 return FALSE;
168                         quoted = (*q == '\\') && !quoted;
169                 }
170                 
171                 tmp = g_strndup (p, q - p);
172                 tmp2 = g_strcompress (tmp);
173                 g_string_truncate (out, 0);
174                 g_string_append (out, tmp2);
175                 g_free (tmp);
176                 g_free (tmp2);
177         }
178         
179         q++;
180         *pos = q;
181         
182         return TRUE;
183 }
184
185 static gboolean
186 scan_int (const char **pos, int *out)
187 {
188         int i = 0;
189         char buf[32];
190         const char *p = *pos;
191         
192         while (g_ascii_isspace (*p))
193                 p++;
194         
195         if (*p < '0' || *p > '9')
196                 return FALSE;
197         
198         while ((*p >= '0') && (*p <= '9') && i < sizeof (buf)) {
199                 buf[i] = *p;
200                 i++;
201                 p++;
202         }
203         
204         if (i == sizeof (buf))
205                 return FALSE;
206         else
207                 buf[i] = '\0';
208         
209         *out = atoi (buf);
210         
211         *pos = p;
212
213         return TRUE;
214 }
215
216 static gboolean
217 skip_space (const char **pos)
218 {
219         const char *p = *pos;
220         
221         while (g_ascii_isspace (*p))
222                 p++;
223   
224         *pos = p;
225         
226         return !(*p == '\0');
227 }
228   
229 #ifdef G_OS_WIN32
230
231 /* DllMain function needed to tuck away the gdk-pixbuf DLL name */
232 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
233
234 static char *
235 get_toplevel (void)
236 {
237   static char *toplevel = NULL;
238
239   if (toplevel == NULL)
240     toplevel = g_win32_get_package_installation_subdirectory
241       (GETTEXT_PACKAGE, dll_name, "");
242
243   return toplevel;
244 }
245
246 static char *
247 get_sysconfdir (void)
248 {
249   static char *sysconfdir = NULL;
250
251   if (sysconfdir == NULL)
252     sysconfdir = g_win32_get_package_installation_subdirectory
253       (GETTEXT_PACKAGE, dll_name, "etc");
254
255   return sysconfdir;
256 }
257
258 #undef GTK_SYSCONFDIR
259 #define GTK_SYSCONFDIR get_sysconfdir()
260
261 static void
262 correct_prefix (gchar **path)
263 {
264   if (strncmp (*path, GTK_PREFIX "/", strlen (GTK_PREFIX "/")) == 0 ||
265       strncmp (*path, GTK_PREFIX "\\", strlen (GTK_PREFIX "\\")) == 0)
266     {
267       /* This is an entry put there by gdk-pixbuf-query-loaders on the
268        * packager's system. On Windows a prebuilt GTK+ package can be
269        * installed in a random location. The gdk-pixbuf.loaders file
270        * distributed in such a package contains paths from the package
271        * builder's machine. Replace the build-time prefix with the
272        * installation prefix on this machine.
273        */
274       gchar *tem = *path;
275       *path = g_strconcat (get_toplevel (), tem + strlen (GTK_PREFIX), NULL);
276       g_free (tem);
277     }
278 }
279
280 #endif  /* G_OS_WIN32 */
281
282 static gchar *
283 gdk_pixbuf_get_module_file (void)
284 {
285   gchar *result = g_strdup (g_getenv ("GDK_PIXBUF_MODULE_FILE"));
286
287   if (!result)
288           result = g_build_filename (GTK_SYSCONFDIR, "gtk-2.0", "gdk-pixbuf.loaders", NULL);
289
290   return result;
291 }
292
293 #endif  /* USE_GMODULE */
294
295 static void 
296 gdk_pixbuf_io_init (void)
297 {
298 #ifdef USE_GMODULE
299         GIOChannel *channel;
300         gchar *line_buf;
301         gsize term;
302         GString *tmp_buf = g_string_new (NULL);
303         gboolean have_error = FALSE;
304         GdkPixbufModule *module = NULL;
305         gchar *filename = gdk_pixbuf_get_module_file ();
306         int flags;
307         int n_patterns = 0;
308         GdkPixbufModulePattern *pattern;
309         GError *error = NULL;
310 #endif
311         GdkPixbufModule *builtin_module ;
312
313         /*  initialize on separate line to avoid compiler warnings in the
314          *  common case of no compiled-in modules.
315          */
316         builtin_module = NULL;
317
318 #define load_one_builtin_module(format)                                 \
319         builtin_module = g_new0 (GdkPixbufModule, 1);                   \
320         builtin_module->module_name = #format;                          \
321         if (_gdk_pixbuf_load_module (builtin_module, NULL))             \
322                 file_formats = g_slist_prepend (file_formats, builtin_module);\
323         else                                                            \
324                 g_free (builtin_module)
325
326 #ifdef INCLUDE_ani
327         load_one_builtin_module (ani);
328 #endif
329 #ifdef INCLUDE_png
330         load_one_builtin_module (png);
331 #endif
332 #ifdef INCLUDE_bmp
333         load_one_builtin_module (bmp);
334 #endif
335 #ifdef INCLUDE_wbmp
336         load_one_builtin_module (wbmp);
337 #endif
338 #ifdef INCLUDE_gif
339         load_one_builtin_module (gif);
340 #endif
341 #ifdef INCLUDE_ico
342         load_one_builtin_module (ico);
343 #endif
344 #ifdef INCLUDE_jpeg
345         load_one_builtin_module (jpeg);
346 #endif
347 #ifdef INCLUDE_pnm
348         load_one_builtin_module (pnm);
349 #endif
350 #ifdef INCLUDE_ras
351         load_one_builtin_module (ras);
352 #endif
353 #ifdef INCLUDE_tiff
354         load_one_builtin_module (tiff);
355 #endif
356 #ifdef INCLUDE_xpm
357         load_one_builtin_module (xpm);
358 #endif
359 #ifdef INCLUDE_xbm
360         load_one_builtin_module (xbm);
361 #endif
362 #ifdef INCLUDE_tga
363         load_one_builtin_module (tga);
364 #endif
365 #ifdef INCLUDE_pcx
366         load_one_builtin_module (pcx);
367 #endif
368 #ifdef INCLUDE_icns
369         load_one_builtin_module (icns);
370 #endif
371 #ifdef INCLUDE_jasper
372         load_one_builtin_module (jasper);
373 #endif
374 #ifdef INCLUDE_gdiplus
375         /* We don't bother having the GDI+ loaders individually selectable
376          * for building in or not.
377          */
378         load_one_builtin_module (ico);
379         load_one_builtin_module (wmf);
380         load_one_builtin_module (emf);
381         load_one_builtin_module (bmp);
382         load_one_builtin_module (gif);
383         load_one_builtin_module (jpeg);
384         load_one_builtin_module (tiff);
385 #endif
386 #ifdef INCLUDE_gdip_png
387         /* Except the gdip-png loader which normally isn't built at all even */
388         load_one_builtin_module (png);
389 #endif
390
391 #undef load_one_builtin_module
392
393 #ifdef USE_GMODULE
394         channel = g_io_channel_new_file (filename, "r",  &error);
395         if (!channel) {
396                 /* Don't bother warning if we have some built-in loaders */
397                 if (file_formats == NULL)
398                         g_warning ("Cannot open pixbuf loader module file '%s': %s",
399                                    filename, error->message);
400                 return;
401         }
402         
403         while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL, &term, NULL) == G_IO_STATUS_NORMAL) {
404                 const char *p;
405                 
406                 p = line_buf;
407
408                 line_buf[term] = 0;
409
410                 if (!skip_space (&p)) {
411                                 /* Blank line marking the end of a module
412                                  */
413                         if (module && *p != '#') {
414 #ifdef G_OS_WIN32
415                                 correct_prefix (&module->module_path);
416 #endif
417                                 file_formats = g_slist_prepend (file_formats, module);
418                                 module = NULL;
419                         }
420                         
421                         goto next_line;
422                 }
423
424                 if (*p == '#') 
425                         goto next_line;
426                 
427                 if (!module) {
428                                 /* Read a module location
429                                  */
430                         module = g_new0 (GdkPixbufModule, 1);
431                         n_patterns = 0;
432                         
433                         if (!scan_string (&p, tmp_buf)) {
434                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
435                                            filename, line_buf);
436                                 have_error = TRUE;
437                         }
438                         module->module_path = g_strdup (tmp_buf->str);
439                 }
440                 else if (!module->module_name) {
441                         module->info = g_new0 (GdkPixbufFormat, 1);
442                         if (!scan_string (&p, tmp_buf)) {
443                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
444                                            filename, line_buf);
445                                 have_error = TRUE;
446                         }
447                         module->info->name =  g_strdup (tmp_buf->str);
448                         module->module_name = module->info->name;
449
450                         if (!scan_int (&p, &flags)) {
451                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
452                                            filename, line_buf);
453                                 have_error = TRUE;
454                         }
455                         module->info->flags = flags;
456                         
457                         if (!scan_string (&p, tmp_buf)) {
458                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
459                                            filename, line_buf);
460                                 have_error = TRUE;
461                         }                       
462                         if (tmp_buf->str[0] != 0)
463                                 module->info->domain = g_strdup (tmp_buf->str);
464
465                         if (!scan_string (&p, tmp_buf)) {
466                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
467                                            filename, line_buf);
468                                 have_error = TRUE;
469                         }                       
470                         module->info->description = g_strdup (tmp_buf->str);
471
472                         if (scan_string (&p, tmp_buf)) {
473                                 module->info->license = g_strdup (tmp_buf->str);
474                         }
475                 }
476                 else if (!module->info->mime_types) {
477                         int n = 1;
478                         module->info->mime_types = g_new0 (gchar*, 1);
479                         while (scan_string (&p, tmp_buf)) {
480                                 if (tmp_buf->str[0] != 0) {
481                                         module->info->mime_types =
482                                                 g_realloc (module->info->mime_types, (n + 1) * sizeof (gchar*));
483                                         module->info->mime_types[n - 1] = g_strdup (tmp_buf->str);
484                                         module->info->mime_types[n] = NULL;
485                                         n++;
486                                 }
487                         }
488                 }
489                 else if (!module->info->extensions) {
490                         int n = 1;
491                         module->info->extensions = g_new0 (gchar*, 1);
492                         while (scan_string (&p, tmp_buf)) {
493                                 if (tmp_buf->str[0] != 0) {
494                                         module->info->extensions =
495                                                 g_realloc (module->info->extensions, (n + 1) * sizeof (gchar*));
496                                         module->info->extensions[n - 1] = g_strdup (tmp_buf->str);
497                                         module->info->extensions[n] = NULL;
498                                         n++;
499                                 }
500                         }
501                 }
502                 else {
503                         n_patterns++;
504                         module->info->signature = (GdkPixbufModulePattern *)
505                                 g_realloc (module->info->signature, (n_patterns + 1) * sizeof (GdkPixbufModulePattern));
506                         pattern = module->info->signature + n_patterns;
507                         pattern->prefix = NULL;
508                         pattern->mask = NULL;
509                         pattern->relevance = 0;
510                         pattern--;
511                         if (!scan_string (&p, tmp_buf))
512                                 goto context_error;
513                         pattern->prefix = g_strdup (tmp_buf->str);
514                         
515                         if (!scan_string (&p, tmp_buf))
516                                 goto context_error;
517                         if (*tmp_buf->str)
518                                 pattern->mask = g_strdup (tmp_buf->str);
519                         else
520                                 pattern->mask = NULL;
521                         
522                         if (!scan_int (&p, &pattern->relevance))
523                                 goto context_error;
524                         
525                         goto next_line;
526
527                 context_error:
528                         g_free (pattern->prefix);
529                         g_free (pattern->mask);
530                         g_free (pattern);
531                         g_warning ("Error parsing loader info in '%s'\n  %s", 
532                                    filename, line_buf);
533                         have_error = TRUE;
534                 }
535         next_line:
536                 g_free (line_buf);
537         }
538         g_string_free (tmp_buf, TRUE);
539         g_io_channel_unref (channel);
540         g_free (filename);
541 #endif
542 }
543
544 #ifdef USE_GMODULE
545
546 /* actually load the image handler - gdk_pixbuf_get_module only get a */
547 /* reference to the module to load, it doesn't actually load it       */
548 /* perhaps these actions should be combined in one function           */
549 static gboolean
550 _gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
551                                   GError         **error)
552 {
553         char *path;
554         GModule *module;
555         gpointer sym;
556                 
557         g_return_val_if_fail (image_module->module == NULL, FALSE);
558
559         path = image_module->module_path;
560         module = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
561
562         if (!module) {
563                 g_set_error (error,
564                              GDK_PIXBUF_ERROR,
565                              GDK_PIXBUF_ERROR_FAILED,
566                              _("Unable to load image-loading module: %s: %s"),
567                              path, g_module_error ());
568                 return FALSE;
569         }
570
571         image_module->module = module;        
572         
573         if (g_module_symbol (module, "fill_vtable", &sym)) {
574                 GdkPixbufModuleFillVtableFunc func = (GdkPixbufModuleFillVtableFunc) sym;
575                 (* func) (image_module);
576                 return TRUE;
577         } else {
578                 g_set_error (error,
579                              GDK_PIXBUF_ERROR,
580                              GDK_PIXBUF_ERROR_FAILED,
581                              _("Image-loading module %s does not export the proper interface; perhaps it's from a different GTK version?"),
582                              path);
583                 return FALSE;
584         }
585 }
586
587 #endif  /* !USE_GMODULE */
588
589 #define module(type) \
590   extern void _gdk_pixbuf__##type##_fill_info   (GdkPixbufFormat *info);   \
591   extern void _gdk_pixbuf__##type##_fill_vtable (GdkPixbufModule *module)
592
593 module (png);
594 module (jpeg);
595 module (gif);
596 module (ico);
597 module (ani);
598 module (ras);
599 module (xpm);
600 module (tiff);
601 module (pnm);
602 module (bmp);
603 module (wbmp);
604 module (xbm);
605 module (tga);
606 module (pcx);
607 module (icns);
608 module (jasper);
609 module (gdip_ico);
610 module (gdip_wmf);
611 module (gdip_emf);
612 module (gdip_bmp);
613 module (gdip_gif);
614 module (gdip_jpeg);
615 module (gdip_png);
616 module (gdip_tiff);
617
618 #undef module
619
620 gboolean
621 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
622                          GError         **error)
623 {
624         gboolean ret;
625         gboolean locked = FALSE;
626         GdkPixbufModuleFillInfoFunc fill_info = NULL;
627         GdkPixbufModuleFillVtableFunc fill_vtable = NULL;
628
629 #define try_module(format,id)                                           \
630         if (fill_info == NULL &&                                        \
631             strcmp (image_module->module_name, #format) == 0) {         \
632                 fill_info = _gdk_pixbuf__##id##_fill_info;              \
633                 fill_vtable = _gdk_pixbuf__##id##_fill_vtable;  \
634         }
635 #ifdef INCLUDE_png      
636         try_module (png,png);
637 #endif
638 #ifdef INCLUDE_bmp
639         try_module (bmp,bmp);
640 #endif
641 #ifdef INCLUDE_wbmp
642         try_module (wbmp,wbmp);
643 #endif
644 #ifdef INCLUDE_gif
645         try_module (gif,gif);
646 #endif
647 #ifdef INCLUDE_ico
648         try_module (ico,ico);
649 #endif
650 #ifdef INCLUDE_ani
651         try_module (ani,ani);
652 #endif
653 #ifdef INCLUDE_jpeg
654         try_module (jpeg,jpeg);
655 #endif
656 #ifdef INCLUDE_pnm
657         try_module (pnm,pnm);
658 #endif
659 #ifdef INCLUDE_ras
660         try_module (ras,ras);
661 #endif
662 #ifdef INCLUDE_tiff
663         try_module (tiff,tiff);
664 #endif
665 #ifdef INCLUDE_xpm
666         try_module (xpm,xpm);
667 #endif
668 #ifdef INCLUDE_xbm
669         try_module (xbm,xbm);
670 #endif
671 #ifdef INCLUDE_tga
672         try_module (tga,tga);
673 #endif
674 #ifdef INCLUDE_pcx
675         try_module (pcx,pcx);
676 #endif
677 #ifdef INCLUDE_icns
678         try_module (icns,icns);
679 #endif
680 #ifdef INCLUDE_jasper
681         try_module (jasper,jasper);
682 #endif
683 #ifdef INCLUDE_gdiplus
684         try_module (ico,gdip_ico);
685         try_module (wmf,gdip_wmf);
686         try_module (emf,gdip_emf);
687         try_module (bmp,gdip_bmp);
688         try_module (gif,gdip_gif);
689         try_module (jpeg,gdip_jpeg);
690         try_module (tiff,gdip_tiff);
691 #endif
692 #ifdef INCLUDE_gdip_png
693         try_module (png,gdip_png);
694 #endif
695
696 #undef try_module
697         
698         if (fill_vtable) {
699                 image_module->module = (void *) 1;
700                 (* fill_vtable) (image_module);
701                 image_module->info = g_new0 (GdkPixbufFormat, 1);
702                 (* fill_info) (image_module->info);
703
704                 return TRUE;
705         }
706
707 #ifdef USE_GMODULE
708
709         /* be extra careful, maybe the module initializes
710          * the thread system
711          */
712         if (g_threads_got_initialized)
713         {
714                 G_LOCK (init_lock);
715                 locked = TRUE;
716         }
717         ret = _gdk_pixbuf_load_module_unlocked (image_module, error);
718         if (locked)
719                 G_UNLOCK (init_lock);
720         return ret;
721
722 #else
723         g_set_error (error,
724                      GDK_PIXBUF_ERROR,
725                      GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
726                      _("Image type '%s' is not supported"),
727                      image_module->module_name);
728
729         return FALSE;
730
731 #endif
732 }
733
734 \f
735
736 GdkPixbufModule *
737 _gdk_pixbuf_get_named_module (const char *name,
738                               GError **error)
739 {
740         GSList *modules;
741
742         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
743                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
744
745                 if (module->info->disabled)
746                         continue;
747
748                 if (!strcmp (name, module->module_name))
749                         return module;
750         }
751
752         g_set_error (error,
753                      GDK_PIXBUF_ERROR,
754                      GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
755                      _("Image type '%s' is not supported"),
756                      name);
757         
758         return NULL;
759 }
760
761 GdkPixbufModule *
762 _gdk_pixbuf_get_module (guchar *buffer, guint size,
763                         const gchar *filename,
764                         GError **error)
765 {
766         GSList *modules;
767
768         GdkPixbufModule *selected = NULL;
769         gchar *display_name = NULL;
770 #ifdef GDK_PIXBUF_USE_GIO_MIME
771         gchar *mime_type;
772         gchar **mimes;
773         gchar *type;
774         gint j;
775
776         mime_type = g_content_type_guess (filename, buffer, size, NULL);
777
778         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
779                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
780                 GdkPixbufFormat *info = module->info;
781
782                 if (info->disabled)
783                         continue;
784
785                 mimes = info->mime_types;
786                 for (j = 0; mimes[j] != NULL; j++) {
787                         type = g_content_type_from_mime_type (mimes[j]);
788                         if (g_ascii_strcasecmp (type, mime_type) == 0) {
789                                 g_free (type);
790                                 selected = module;
791                                 break;
792                         }
793                         g_free (type);
794                 }
795         }
796         g_free (mime_type);
797 #else
798         gint score, best = 0;
799
800         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
801                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
802
803                 if (module->info->disabled)
804                         continue;
805
806                 score = format_check (module, buffer, size);
807                 if (score > best) {
808                         best = score; 
809                         selected = module;
810                 }
811                 if (score >= 100) 
812                         break;
813         }
814 #endif
815
816         if (selected != NULL)
817                 return selected;
818
819         if (filename)
820         {
821                 display_name = g_filename_display_name (filename);
822                 g_set_error (error,
823                              GDK_PIXBUF_ERROR,
824                              GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
825                              _("Couldn't recognize the image file format for file '%s'"),
826                              display_name);
827                 g_free (display_name);
828         }
829         else
830                 g_set_error_literal (error,
831                                      GDK_PIXBUF_ERROR,
832                                      GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
833                                      _("Unrecognized image file format"));
834
835
836         return NULL;
837 }
838
839
840 static void
841 prepared_notify (GdkPixbuf *pixbuf, 
842                  GdkPixbufAnimation *anim, 
843                  gpointer user_data)
844 {
845         if (pixbuf != NULL)
846                 g_object_ref (pixbuf);
847         *((GdkPixbuf **)user_data) = pixbuf;
848 }
849
850 GdkPixbuf *
851 _gdk_pixbuf_generic_image_load (GdkPixbufModule *module,
852                                 FILE *f,
853                                 GError **error)
854 {
855         guchar buffer[LOAD_BUFFER_SIZE];
856         size_t length;
857         GdkPixbuf *pixbuf = NULL;
858         GdkPixbufAnimation *animation = NULL;
859         gpointer context;
860         gboolean locked;
861
862         locked = _gdk_pixbuf_lock (module);
863
864         if (module->load != NULL) {
865                 pixbuf = (* module->load) (f, error);
866         } else if (module->begin_load != NULL) {
867                 
868                 context = module->begin_load (NULL, prepared_notify, NULL, &pixbuf, error);
869         
870                 if (!context)
871                         goto out;
872                 
873                 while (!feof (f) && !ferror (f)) {
874                         length = fread (buffer, 1, sizeof (buffer), f);
875                         if (length > 0)
876                                 if (!module->load_increment (context, buffer, length, error)) {
877                                         module->stop_load (context, NULL);
878                                         if (pixbuf != NULL) {
879                                                 g_object_unref (pixbuf);
880                                                 pixbuf = NULL;
881                                         }
882                                         goto out;
883                                 }
884                 }
885                 
886                 if (!module->stop_load (context, error)) {
887                         if (pixbuf != NULL) {
888                                 g_object_unref (pixbuf);
889                                 pixbuf = NULL;
890                         }
891                 }
892         } else if (module->load_animation != NULL) {
893                 animation = (* module->load_animation) (f, error);
894                 if (animation != NULL) {
895                         pixbuf = gdk_pixbuf_animation_get_static_image (animation);
896
897                         g_object_ref (pixbuf);
898                         g_object_unref (animation);
899                 }
900         }
901
902  out:
903         if (locked)
904                 _gdk_pixbuf_unlock (module);
905         return pixbuf;
906 }
907
908 /**
909  * gdk_pixbuf_new_from_file:
910  * @filename: Name of file to load, in the GLib file name encoding
911  * @error: Return location for an error
912  *
913  * Creates a new pixbuf by loading an image from a file.  The file format is
914  * detected automatically. If %NULL is returned, then @error will be set.
915  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
916  *
917  * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if
918  * any of several error conditions occurred:  the file could not be opened,
919  * there was no loader for the file's format, there was not enough memory to
920  * allocate the image buffer, or the image file contained invalid data.
921  **/
922 GdkPixbuf *
923 gdk_pixbuf_new_from_file (const char *filename,
924                           GError    **error)
925 {
926         GdkPixbuf *pixbuf;
927         int size;
928         FILE *f;
929         guchar buffer[SNIFF_BUFFER_SIZE];
930         GdkPixbufModule *image_module;
931         gchar *display_name;
932
933         g_return_val_if_fail (filename != NULL, NULL);
934         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
935         
936         display_name = g_filename_display_name (filename);      
937
938         f = g_fopen (filename, "rb");
939         if (!f) {
940                 gint save_errno = errno;
941                 g_set_error (error,
942                              G_FILE_ERROR,
943                              g_file_error_from_errno (save_errno),
944                              _("Failed to open file '%s': %s"),
945                              display_name,
946                              g_strerror (save_errno));
947                 g_free (display_name);
948                 return NULL;
949         }
950
951         size = fread (&buffer, 1, sizeof (buffer), f);
952         if (size == 0) {
953                 g_set_error (error,
954                              GDK_PIXBUF_ERROR,
955                              GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
956                              _("Image file '%s' contains no data"),
957                              display_name);
958                 g_free (display_name);
959                 fclose (f);
960                 return NULL;
961         }
962
963         image_module = _gdk_pixbuf_get_module (buffer, size, filename, error);
964         if (image_module == NULL) {
965                 g_free (display_name);
966                 fclose (f);
967                 return NULL;
968         }
969
970         if (image_module->module == NULL)
971                 if (!_gdk_pixbuf_load_module (image_module, error)) {
972                         g_free (display_name);
973                         fclose (f);
974                         return NULL;
975                 }
976
977         fseek (f, 0, SEEK_SET);
978         pixbuf = _gdk_pixbuf_generic_image_load (image_module, f, error);
979         fclose (f);
980
981         if (pixbuf == NULL && error != NULL && *error == NULL) {
982
983                 /* I don't trust these crufty longjmp()'ing image libs
984                  * to maintain proper error invariants, and I don't
985                  * want user code to segfault as a result. We need to maintain
986                  * the invariant that error gets set if NULL is returned.
987                  */
988
989                 g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
990                 g_set_error (error,
991                              GDK_PIXBUF_ERROR,
992                              GDK_PIXBUF_ERROR_FAILED,
993                              _("Failed to load image '%s': reason not known, probably a corrupt image file"),
994                              display_name);
995         } else if (error != NULL && *error != NULL) {
996
997           /* Add the filename to the error message */
998           GError *e = *error;
999           gchar  *old;
1000
1001           old = e->message;
1002           e->message = g_strdup_printf (_("Failed to load image '%s': %s"),
1003                                         display_name,
1004                                         old);
1005           g_free (old);
1006         }
1007
1008         g_free (display_name);
1009         return pixbuf;
1010 }
1011
1012 #ifdef G_OS_WIN32
1013
1014 #undef gdk_pixbuf_new_from_file
1015 GdkPixbuf *
1016 gdk_pixbuf_new_from_file (const char *filename,
1017                           GError    **error)
1018 {
1019         gchar *utf8_filename =
1020                 g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1021         GdkPixbuf *retval;
1022
1023         if (utf8_filename == NULL)
1024                 return NULL;
1025
1026         retval = gdk_pixbuf_new_from_file_utf8 (utf8_filename, error);
1027
1028         g_free (utf8_filename);
1029
1030         return retval;
1031 }
1032 #endif
1033
1034
1035 /**
1036  * gdk_pixbuf_new_from_file_at_size:
1037  * @filename: Name of file to load, in the GLib file name encoding
1038  * @width: The width the image should have or -1 to not constrain the width
1039  * @height: The height the image should have or -1 to not constrain the height
1040  * @error: Return location for an error
1041  *
1042  * Creates a new pixbuf by loading an image from a file.  
1043  * The file format is detected automatically. If %NULL is returned, then 
1044  * @error will be set. Possible errors are in the #GDK_PIXBUF_ERROR and 
1045  * #G_FILE_ERROR domains.
1046  *
1047  * The image will be scaled to fit in the requested size, preserving
1048  * the image's aspect ratio. Note that the returned pixbuf may be smaller
1049  * than @width x @height, if the aspect ratio requires it. To load
1050  * and image at the requested size, regardless of aspect ratio, use
1051  * gdk_pixbuf_new_from_file_at_scale().
1052  *
1053  * Return value: A newly-created pixbuf with a reference count of 1, or 
1054  * %NULL if any of several error conditions occurred:  the file could not 
1055  * be opened, there was no loader for the file's format, there was not 
1056  * enough memory to allocate the image buffer, or the image file contained 
1057  * invalid data.
1058  *
1059  * Since: 2.4
1060  **/
1061 GdkPixbuf *
1062 gdk_pixbuf_new_from_file_at_size (const char *filename,
1063                                   int         width, 
1064                                   int         height,
1065                                   GError    **error)
1066 {
1067         return gdk_pixbuf_new_from_file_at_scale (filename, 
1068                                                   width, height, 
1069                                                   TRUE, error);
1070 }
1071
1072 #ifdef G_OS_WIN32
1073
1074 #undef gdk_pixbuf_new_from_file_at_size
1075
1076 GdkPixbuf *
1077 gdk_pixbuf_new_from_file_at_size (const char *filename,
1078                                   int         width, 
1079                                   int         height,
1080                                   GError    **error)
1081 {
1082         gchar *utf8_filename =
1083                 g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1084         GdkPixbuf *retval;
1085
1086         if (utf8_filename == NULL)
1087                 return NULL;
1088
1089         retval = gdk_pixbuf_new_from_file_at_size_utf8 (utf8_filename,
1090                                                         width, height,
1091                                                         error);
1092
1093         g_free (utf8_filename);
1094
1095         return retval;
1096 }
1097 #endif
1098
1099 typedef struct {
1100         gint width;
1101         gint height;
1102         gboolean preserve_aspect_ratio;
1103 } AtScaleData; 
1104
1105 static void
1106 at_scale_size_prepared_cb (GdkPixbufLoader *loader, 
1107                            int              width,
1108                            int              height,
1109                            gpointer         data)
1110 {
1111         AtScaleData *info = data;
1112
1113         g_return_if_fail (width > 0 && height > 0);
1114
1115         if (info->preserve_aspect_ratio && 
1116             (info->width > 0 || info->height > 0)) {
1117                 if (info->width < 0)
1118                 {
1119                         width = width * (double)info->height/(double)height;
1120                         height = info->height;
1121                 }
1122                 else if (info->height < 0)
1123                 {
1124                         height = height * (double)info->width/(double)width;
1125                         width = info->width;
1126                 }
1127                 else if ((double)height * (double)info->width >
1128                          (double)width * (double)info->height) {
1129                         width = 0.5 + (double)width * (double)info->height / (double)height;
1130                         height = info->height;
1131                 } else {
1132                         height = 0.5 + (double)height * (double)info->width / (double)width;
1133                         width = info->width;
1134                 }
1135         } else {
1136                 if (info->width > 0)
1137                         width = info->width;
1138                 if (info->height > 0)
1139                         height = info->height;
1140         }
1141         
1142         width = MAX (width, 1);
1143         height = MAX (height, 1);
1144
1145         gdk_pixbuf_loader_set_size (loader, width, height);
1146 }
1147
1148 /**
1149  * gdk_pixbuf_new_from_file_at_scale:
1150  * @filename: Name of file to load, in the GLib file name encoding
1151  * @width: The width the image should have or -1 to not constrain the width
1152  * @height: The height the image should have or -1 to not constrain the height
1153  * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1154  * @error: Return location for an error
1155  *
1156  * Creates a new pixbuf by loading an image from a file.  The file format is
1157  * detected automatically. If %NULL is returned, then @error will be set.
1158  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
1159  * The image will be scaled to fit in the requested size, optionally preserving
1160  * the image's aspect ratio. 
1161  *
1162  * When preserving the aspect ratio, a @width of -1 will cause the image
1163  * to be scaled to the exact given height, and a @height of -1 will cause
1164  * the image to be scaled to the exact given width. When not preserving
1165  * aspect ratio, a @width or @height of -1 means to not scale the image 
1166  * at all in that dimension. Negative values for @width and @height are 
1167  * allowed since 2.8.
1168  *
1169  * Return value: A newly-created pixbuf with a reference count of 1, or %NULL 
1170  * if any of several error conditions occurred:  the file could not be opened,
1171  * there was no loader for the file's format, there was not enough memory to
1172  * allocate the image buffer, or the image file contained invalid data.
1173  *
1174  * Since: 2.6
1175  **/
1176 GdkPixbuf *
1177 gdk_pixbuf_new_from_file_at_scale (const char *filename,
1178                                    int         width, 
1179                                    int         height,
1180                                    gboolean    preserve_aspect_ratio,
1181                                    GError    **error)
1182 {
1183
1184         GdkPixbufLoader *loader;
1185         GdkPixbuf       *pixbuf;
1186         guchar buffer[LOAD_BUFFER_SIZE];
1187         int length;
1188         FILE *f;
1189         AtScaleData info;
1190         GdkPixbufAnimation *animation;
1191         GdkPixbufAnimationIter *iter;
1192         gboolean has_frame;
1193
1194         g_return_val_if_fail (filename != NULL, NULL);
1195         g_return_val_if_fail (width > 0 || width == -1, NULL);
1196         g_return_val_if_fail (height > 0 || height == -1, NULL);
1197
1198         f = g_fopen (filename, "rb");
1199         if (!f) {
1200                 gint save_errno = errno;
1201                 gchar *display_name = g_filename_display_name (filename);
1202                 g_set_error (error,
1203                              G_FILE_ERROR,
1204                              g_file_error_from_errno (save_errno),
1205                              _("Failed to open file '%s': %s"),
1206                              display_name,
1207                              g_strerror (save_errno));
1208                 g_free (display_name);
1209                 return NULL;
1210         }
1211
1212         loader = gdk_pixbuf_loader_new ();
1213
1214         info.width = width;
1215         info.height = height;
1216         info.preserve_aspect_ratio = preserve_aspect_ratio;
1217
1218         g_signal_connect (loader, "size-prepared", 
1219                           G_CALLBACK (at_scale_size_prepared_cb), &info);
1220
1221         has_frame = FALSE;
1222         while (!has_frame && !feof (f) && !ferror (f)) {
1223                 length = fread (buffer, 1, sizeof (buffer), f);
1224                 if (length > 0)
1225                         if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
1226                                 gdk_pixbuf_loader_close (loader, NULL);
1227                                 fclose (f);
1228                                 g_object_unref (loader);
1229                                 return NULL;
1230                         }
1231                 
1232                 animation = gdk_pixbuf_loader_get_animation (loader);
1233                 if (animation) {
1234                         iter = gdk_pixbuf_animation_get_iter (animation, NULL);
1235                         if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) {
1236                                 has_frame = TRUE;
1237                         }
1238                         g_object_unref (iter);
1239                 }
1240         }
1241
1242         fclose (f);
1243
1244         if (!gdk_pixbuf_loader_close (loader, error) && !has_frame) {
1245                 g_object_unref (loader);
1246                 return NULL;
1247         }
1248
1249         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1250
1251         if (!pixbuf) {
1252                 gchar *display_name = g_filename_display_name (filename);
1253                 g_object_unref (loader);
1254                 g_set_error (error,
1255                              GDK_PIXBUF_ERROR,
1256                              GDK_PIXBUF_ERROR_FAILED,
1257                              _("Failed to load image '%s': reason not known, probably a corrupt image file"),
1258                              display_name);
1259                 g_free (display_name);
1260                 return NULL;
1261         }
1262
1263         g_object_ref (pixbuf);
1264
1265         g_object_unref (loader);
1266
1267         return pixbuf;
1268 }
1269
1270 #ifdef G_OS_WIN32
1271
1272 #undef gdk_pixbuf_new_from_file_at_scale
1273
1274 GdkPixbuf *
1275 gdk_pixbuf_new_from_file_at_scale (const char *filename,
1276                                    int         width, 
1277                                    int         height,
1278                                    gboolean    preserve_aspect_ratio,
1279                                    GError    **error)
1280 {
1281         gchar *utf8_filename =
1282                 g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1283         GdkPixbuf *retval;
1284
1285         if (utf8_filename == NULL)
1286                 return NULL;
1287
1288         retval = gdk_pixbuf_new_from_file_at_scale_utf8 (utf8_filename,
1289                                                          width, height,
1290                                                          preserve_aspect_ratio,
1291                                                          error);
1292
1293         g_free (utf8_filename);
1294
1295         return retval;
1296 }
1297 #endif
1298
1299
1300 static GdkPixbuf *
1301 load_from_stream (GdkPixbufLoader  *loader,
1302                   GInputStream     *stream,
1303                   GCancellable     *cancellable,
1304                   GError          **error)
1305 {
1306         GdkPixbuf *pixbuf;
1307         gssize n_read;
1308         guchar buffer[LOAD_BUFFER_SIZE];
1309         gboolean res;
1310
1311         res = TRUE;
1312         while (1) { 
1313                 n_read = g_input_stream_read (stream, 
1314                                               buffer, 
1315                                               sizeof (buffer), 
1316                                               cancellable, 
1317                                               error);
1318                 if (n_read < 0) {
1319                         res = FALSE;
1320                         error = NULL; /* Ignore further errors */
1321                         break;
1322                 }
1323
1324                 if (n_read == 0)
1325                         break;
1326
1327                 if (!gdk_pixbuf_loader_write (loader, 
1328                                               buffer, 
1329                                               n_read, 
1330                                               error)) {
1331                         res = FALSE;
1332                         error = NULL;
1333                         break;
1334                 }
1335         }
1336
1337         if (!gdk_pixbuf_loader_close (loader, error)) {
1338                 res = FALSE;
1339                 error = NULL;
1340         }
1341
1342         pixbuf = NULL;
1343         if (res) {
1344                 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1345                 if (pixbuf)
1346                         g_object_ref (pixbuf);
1347         }
1348
1349         return pixbuf;
1350 }
1351
1352
1353 /**
1354  * gdk_pixbuf_new_from_stream_at_scale:
1355  * @stream:  a #GInputStream to load the pixbuf from
1356  * @width: The width the image should have or -1 to not constrain the width
1357  * @height: The height the image should have or -1 to not constrain the height
1358  * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1359  * @cancellable: optional #GCancellable object, %NULL to ignore
1360  * @error: Return location for an error
1361  *
1362  * Creates a new pixbuf by loading an image from an input stream.  
1363  *
1364  * The file format is detected automatically. If %NULL is returned, then 
1365  * @error will be set. The @cancellable can be used to abort the operation
1366  * from another thread. If the operation was cancelled, the error 
1367  * %GIO_ERROR_CANCELLED will be returned. Other possible errors are in 
1368  * the #GDK_PIXBUF_ERROR and %G_IO_ERROR domains. 
1369  *
1370  * The image will be scaled to fit in the requested size, optionally 
1371  * preserving the image's aspect ratio. When preserving the aspect ratio, 
1372  * a @width of -1 will cause the image to be scaled to the exact given 
1373  * height, and a @height of -1 will cause the image to be scaled to the 
1374  * exact given width. When not preserving aspect ratio, a @width or 
1375  * @height of -1 means to not scale the image at all in that dimension.
1376  *
1377  * The stream is not closed.
1378  *
1379  * Return value: A newly-created pixbuf, or %NULL if any of several error 
1380  * conditions occurred: the file could not be opened, the image format is 
1381  * not supported, there was not enough memory to allocate the image buffer, 
1382  * the stream contained invalid data, or the operation was cancelled.
1383  *
1384  * Since: 2.14
1385  */
1386 GdkPixbuf *
1387 gdk_pixbuf_new_from_stream_at_scale (GInputStream  *stream,
1388                                      gint           width,
1389                                      gint           height,
1390                                      gboolean       preserve_aspect_ratio,
1391                                      GCancellable  *cancellable,
1392                                      GError       **error)
1393 {
1394         GdkPixbufLoader *loader;
1395         GdkPixbuf *pixbuf;
1396         AtScaleData info;
1397
1398         loader = gdk_pixbuf_loader_new ();
1399
1400         info.width = width;
1401         info.height = height;
1402         info.preserve_aspect_ratio = preserve_aspect_ratio;
1403
1404         g_signal_connect (loader, "size-prepared", 
1405                           G_CALLBACK (at_scale_size_prepared_cb), &info);
1406
1407         pixbuf = load_from_stream (loader, stream, cancellable, error);
1408         g_object_unref (loader);
1409
1410         return pixbuf;
1411 }
1412
1413 /**
1414  * gdk_pixbuf_new_from_stream:
1415  * @stream:  a #GInputStream to load the pixbuf from
1416  * @cancellable: optional #GCancellable object, %NULL to ignore
1417  * @error: Return location for an error
1418  *
1419  * Creates a new pixbuf by loading an image from an input stream.  
1420  *
1421  * The file format is detected automatically. If %NULL is returned, then 
1422  * @error will be set. The @cancellable can be used to abort the operation
1423  * from another thread. If the operation was cancelled, the error 
1424  * %GIO_ERROR_CANCELLED will be returned. Other possible errors are in 
1425  * the #GDK_PIXBUF_ERROR and %G_IO_ERROR domains. 
1426  *
1427  * The stream is not closed.
1428  *
1429  * Return value: A newly-created pixbuf, or %NULL if any of several error 
1430  * conditions occurred: the file could not be opened, the image format is 
1431  * not supported, there was not enough memory to allocate the image buffer, 
1432  * the stream contained invalid data, or the operation was cancelled.
1433  *
1434  * Since: 2.14
1435  **/
1436 GdkPixbuf *
1437 gdk_pixbuf_new_from_stream (GInputStream  *stream,
1438                             GCancellable  *cancellable,
1439                             GError       **error)
1440 {
1441         GdkPixbuf *pixbuf;
1442         GdkPixbufLoader *loader;
1443
1444         loader = gdk_pixbuf_loader_new ();
1445         pixbuf = load_from_stream (loader, stream, cancellable, error);
1446         g_object_unref (loader);
1447
1448         return pixbuf;
1449 }
1450
1451 static void
1452 info_cb (GdkPixbufLoader *loader, 
1453          int              width,
1454          int              height,
1455          gpointer         data)
1456 {
1457         struct {
1458                 GdkPixbufFormat *format;
1459                 int width;
1460                 int height;
1461         } *info = data;
1462
1463         g_return_if_fail (width > 0 && height > 0);
1464
1465         info->format = gdk_pixbuf_loader_get_format (loader);
1466         info->width = width;
1467         info->height = height;
1468
1469         gdk_pixbuf_loader_set_size (loader, 0, 0);
1470 }
1471
1472 /**
1473  * gdk_pixbuf_get_file_info:
1474  * @filename: The name of the file to identify.
1475  * @width: Return location for the width of the image, or %NULL
1476  * @height: Return location for the height of the image, or %NULL
1477  * 
1478  * Parses an image file far enough to determine its format and size.
1479  * 
1480  * Returns: A #GdkPixbufFormat describing the image format of the file 
1481  *    or %NULL if the image format wasn't recognized. The return value 
1482  *    is owned by GdkPixbuf and should not be freed.
1483  *
1484  * Since: 2.4
1485  **/
1486 GdkPixbufFormat *
1487 gdk_pixbuf_get_file_info (const gchar  *filename,
1488                           gint         *width, 
1489                           gint         *height)
1490 {
1491         GdkPixbufLoader *loader;
1492         guchar buffer[SNIFF_BUFFER_SIZE];
1493         int length;
1494         FILE *f;
1495         struct {
1496                 GdkPixbufFormat *format;
1497                 gint width;
1498                 gint height;
1499         } info;
1500
1501         g_return_val_if_fail (filename != NULL, NULL);
1502
1503         f = g_fopen (filename, "rb");
1504         if (!f)
1505                 return NULL;
1506
1507         loader = gdk_pixbuf_loader_new ();
1508
1509         info.format = NULL;
1510         info.width = -1;
1511         info.height = -1;
1512                 
1513         g_signal_connect (loader, "size-prepared", G_CALLBACK (info_cb), &info);
1514
1515         while (!feof (f) && !ferror (f)) {
1516                 length = fread (buffer, 1, sizeof (buffer), f);
1517                 if (length > 0) {
1518                         if (!gdk_pixbuf_loader_write (loader, buffer, length, NULL))
1519                                 break;
1520                 }
1521                 if (info.format != NULL)
1522                         break;
1523         }
1524
1525         fclose (f);
1526         gdk_pixbuf_loader_close (loader, NULL);
1527         g_object_unref (loader);
1528
1529         if (width) 
1530                 *width = info.width;
1531         if (height) 
1532                 *height = info.height;
1533
1534         return info.format;
1535 }
1536
1537 /**
1538  * gdk_pixbuf_new_from_xpm_data:
1539  * @data: Pointer to inline XPM data.
1540  *
1541  * Creates a new pixbuf by parsing XPM data in memory.  This data is commonly
1542  * the result of including an XPM file into a program's C source.
1543  *
1544  * Return value: A newly-created pixbuf with a reference count of 1.
1545  **/
1546 GdkPixbuf *
1547 gdk_pixbuf_new_from_xpm_data (const char **data)
1548 {
1549         GdkPixbuf *(* load_xpm_data) (const char **data);
1550         GdkPixbuf *pixbuf;
1551         GError *error = NULL;
1552         GdkPixbufModule *xpm_module;
1553         gboolean locked;
1554
1555         g_return_val_if_fail (data != NULL, NULL);
1556
1557         xpm_module = _gdk_pixbuf_get_named_module ("xpm", &error);
1558         if (xpm_module == NULL) {
1559                 g_warning ("Error loading XPM image loader: %s", error->message);
1560                 g_error_free (error);
1561                 return NULL;
1562         }
1563
1564         if (xpm_module->module == NULL) {
1565                 if (!_gdk_pixbuf_load_module (xpm_module, &error)) {
1566                         g_warning ("Error loading XPM image loader: %s", error->message);
1567                         g_error_free (error);
1568                         return NULL;
1569                 }
1570         }
1571
1572         locked = _gdk_pixbuf_lock (xpm_module);
1573
1574         if (xpm_module->load_xpm_data == NULL) {
1575                 g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
1576                 pixbuf = NULL;
1577         } else {
1578                 load_xpm_data = xpm_module->load_xpm_data;
1579                 pixbuf = (* load_xpm_data) (data);
1580         }
1581         
1582         if (locked)
1583                 _gdk_pixbuf_unlock (xpm_module);
1584         return pixbuf;
1585 }
1586
1587 static void
1588 collect_save_options (va_list   opts,
1589                       gchar  ***keys,
1590                       gchar  ***vals)
1591 {
1592   gchar *key;
1593   gchar *val;
1594   gchar *next;
1595   gint count;
1596
1597   count = 0;
1598   *keys = NULL;
1599   *vals = NULL;
1600   
1601   next = va_arg (opts, gchar*);
1602   while (next)
1603     {
1604       key = next;
1605       val = va_arg (opts, gchar*);
1606
1607       ++count;
1608
1609       /* woo, slow */
1610       *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
1611       *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
1612       
1613       (*keys)[count-1] = g_strdup (key);
1614       (*vals)[count-1] = g_strdup (val);
1615
1616       (*keys)[count] = NULL;
1617       (*vals)[count] = NULL;
1618       
1619       next = va_arg (opts, gchar*);
1620     }
1621 }
1622
1623 static gboolean
1624 save_to_file_callback (const gchar *buf,
1625                        gsize        count,
1626                        GError     **error,
1627                        gpointer     data)
1628 {
1629         FILE *filehandle = data;
1630         gsize n;
1631
1632         n = fwrite (buf, 1, count, filehandle);
1633         if (n != count) {
1634                 gint save_errno = errno;
1635                 g_set_error (error,
1636                              G_FILE_ERROR,
1637                              g_file_error_from_errno (save_errno),
1638                              _("Error writing to image file: %s"),
1639                              g_strerror (save_errno));
1640                 return FALSE;
1641         }
1642         return TRUE;
1643 }
1644
1645 static gboolean
1646 gdk_pixbuf_real_save (GdkPixbuf     *pixbuf, 
1647                       FILE          *filehandle, 
1648                       const char    *type, 
1649                       gchar        **keys,
1650                       gchar        **values,
1651                       GError       **error)
1652 {
1653         gboolean ret;
1654         GdkPixbufModule *image_module = NULL;       
1655         gboolean locked;
1656
1657         image_module = _gdk_pixbuf_get_named_module (type, error);
1658
1659         if (image_module == NULL)
1660                 return FALSE;
1661        
1662         if (image_module->module == NULL)
1663                 if (!_gdk_pixbuf_load_module (image_module, error))
1664                         return FALSE;
1665
1666         locked = _gdk_pixbuf_lock (image_module);
1667
1668         if (image_module->save) {
1669                 /* save normally */
1670                 ret = (* image_module->save) (filehandle, pixbuf,
1671                                               keys, values,
1672                                               error);
1673         } else if (image_module->save_to_callback) {
1674                 /* save with simple callback */
1675                 ret = (* image_module->save_to_callback) (save_to_file_callback,
1676                                                           filehandle, pixbuf,
1677                                                           keys, values,
1678                                                           error);
1679         } else {
1680                 /* can't save */
1681                 g_set_error (error,
1682                              GDK_PIXBUF_ERROR,
1683                              GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
1684                              _("This build of gdk-pixbuf does not support saving the image format: %s"),
1685                              type);
1686                 ret = FALSE;
1687         }
1688
1689         if (locked)
1690                 _gdk_pixbuf_unlock (image_module);
1691         return ret;
1692 }
1693
1694 #define TMP_FILE_BUF_SIZE 4096
1695
1696 static gboolean
1697 save_to_callback_with_tmp_file (GdkPixbufModule   *image_module,
1698                                 GdkPixbuf         *pixbuf,
1699                                 GdkPixbufSaveFunc  save_func,
1700                                 gpointer           user_data,
1701                                 gchar            **keys,
1702                                 gchar            **values,
1703                                 GError           **error)
1704 {
1705         int fd;
1706         FILE *f = NULL;
1707         gboolean retval = FALSE;
1708         gchar *buf = NULL;
1709         gsize n;
1710         gchar *filename = NULL;
1711         gboolean locked;
1712
1713         buf = g_try_malloc (TMP_FILE_BUF_SIZE);
1714         if (buf == NULL) {
1715                 g_set_error_literal (error,
1716                                      GDK_PIXBUF_ERROR,
1717                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1718                                      _("Insufficient memory to save image to callback"));
1719                 goto end;
1720         }
1721
1722         fd = g_file_open_tmp ("gdkpixbuf-save-tmp.XXXXXX", &filename, error);
1723         if (fd == -1)
1724                 goto end;
1725         f = fdopen (fd, "wb+");
1726         if (f == NULL) {
1727                 gint save_errno = errno;
1728                 g_set_error_literal (error,
1729                                      G_FILE_ERROR,
1730                                      g_file_error_from_errno (save_errno),
1731                                      _("Failed to open temporary file"));
1732                 goto end;
1733         }
1734
1735         locked = _gdk_pixbuf_lock (image_module);
1736         retval = (image_module->save) (f, pixbuf, keys, values, error);
1737         if (locked)
1738                 _gdk_pixbuf_unlock (image_module);
1739         if (!retval)
1740                 goto end;
1741
1742         rewind (f);
1743         for (;;) {
1744                 n = fread (buf, 1, TMP_FILE_BUF_SIZE, f);
1745                 if (n > 0) {
1746                         if (!save_func (buf, n, error, user_data))
1747                                 goto end;
1748                 }
1749                 if (n != TMP_FILE_BUF_SIZE) 
1750                         break;
1751         }
1752         if (ferror (f)) {
1753                 gint save_errno = errno;
1754                 g_set_error_literal (error,
1755                                      G_FILE_ERROR,
1756                                      g_file_error_from_errno (save_errno),
1757                                      _("Failed to read from temporary file"));
1758                 goto end;
1759         }
1760         retval = TRUE;
1761
1762  end:
1763         /* cleanup and return retval */
1764         if (f)
1765                 fclose (f);
1766         if (filename) {
1767                 g_unlink (filename);
1768                 g_free (filename);
1769         }
1770         g_free (buf);
1771
1772         return retval;
1773 }
1774
1775 static gboolean
1776 gdk_pixbuf_real_save_to_callback (GdkPixbuf         *pixbuf,
1777                                   GdkPixbufSaveFunc  save_func,
1778                                   gpointer           user_data,
1779                                   const char        *type, 
1780                                   gchar            **keys,
1781                                   gchar            **values,
1782                                   GError           **error)
1783 {
1784         gboolean ret;
1785         GdkPixbufModule *image_module = NULL;       
1786         gboolean locked;
1787
1788         image_module = _gdk_pixbuf_get_named_module (type, error);
1789
1790         if (image_module == NULL)
1791                 return FALSE;
1792        
1793         if (image_module->module == NULL)
1794                 if (!_gdk_pixbuf_load_module (image_module, error))
1795                         return FALSE;
1796
1797         locked = _gdk_pixbuf_lock (image_module);
1798
1799         if (image_module->save_to_callback) {
1800                 /* save normally */
1801                 ret = (* image_module->save_to_callback) (save_func, user_data, 
1802                                                           pixbuf, keys, values,
1803                                                           error);
1804         } else if (image_module->save) {
1805                 /* use a temporary file */
1806                 ret = save_to_callback_with_tmp_file (image_module, pixbuf,
1807                                                       save_func, user_data, 
1808                                                       keys, values,
1809                                                       error);
1810         } else {
1811                 /* can't save */
1812                 g_set_error (error,
1813                              GDK_PIXBUF_ERROR,
1814                              GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
1815                              _("This build of gdk-pixbuf does not support saving the image format: %s"),
1816                              type);
1817                 ret = FALSE;
1818         }
1819
1820         if (locked)
1821                 _gdk_pixbuf_unlock (image_module);
1822         return ret;
1823 }
1824
1825  
1826 /**
1827  * gdk_pixbuf_save:
1828  * @pixbuf: a #GdkPixbuf.
1829  * @filename: name of file to save.
1830  * @type: name of file format.
1831  * @error: return location for error, or %NULL
1832  * @Varargs: list of key-value save options
1833  *
1834  * Saves pixbuf to a file in format @type. By default, "jpeg", "png", "ico" 
1835  * and "bmp" are possible file formats to save in, but more formats may be
1836  * installed. The list of all writable formats can be determined in the 
1837  * following way:
1838  *
1839  * |[
1840  * void add_if_writable (GdkPixbufFormat *data, GSList **list)
1841  * {
1842  *   if (gdk_pixbuf_format_is_writable (data))
1843  *     *list = g_slist_prepend (*list, data);
1844  * }
1845  * 
1846  * GSList *formats = gdk_pixbuf_get_formats ();
1847  * GSList *writable_formats = NULL;
1848  * g_slist_foreach (formats, add_if_writable, &writable_formats);
1849  * g_slist_free (formats);
1850  * ]|
1851  *
1852  * If @error is set, %FALSE will be returned. Possible errors include 
1853  * those in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
1854  *
1855  * The variable argument list should be %NULL-terminated; if not empty,
1856  * it should contain pairs of strings that modify the save
1857  * parameters. For example:
1858  * <informalexample><programlisting>
1859  * gdk_pixbuf_save (pixbuf, handle, "jpeg", &amp;error,
1860  *                  "quality", "100", NULL);
1861  * </programlisting></informalexample>
1862  *
1863  * Currently only few parameters exist. JPEG images can be saved with a
1864  * "quality" parameter; its value should be in the range [0,100].
1865  *
1866  * Text chunks can be attached to PNG images by specifying parameters of
1867  * the form "tEXt::key", where key is an ASCII string of length 1-79.
1868  * The values are UTF-8 encoded strings. The PNG compression level can
1869  * be specified using the "compression" parameter; it's value is in an
1870  * integer in the range of [0,9].
1871  *
1872  * ICO images can be saved in depth 16, 24, or 32, by using the "depth"
1873  * parameter. When the ICO saver is given "x_hot" and "y_hot" parameters,
1874  * it produces a CUR instead of an ICO.
1875  *
1876  * Return value: whether an error was set
1877  **/
1878
1879 gboolean
1880 gdk_pixbuf_save (GdkPixbuf  *pixbuf, 
1881                  const char *filename, 
1882                  const char *type, 
1883                  GError    **error,
1884                  ...)
1885 {
1886         gchar **keys = NULL;
1887         gchar **values = NULL;
1888         va_list args;
1889         gboolean result;
1890
1891         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1892         
1893         va_start (args, error);
1894         
1895         collect_save_options (args, &keys, &values);
1896         
1897         va_end (args);
1898
1899         result = gdk_pixbuf_savev (pixbuf, filename, type,
1900                                    keys, values,
1901                                    error);
1902
1903         g_strfreev (keys);
1904         g_strfreev (values);
1905
1906         return result;
1907 }
1908
1909 #ifdef G_OS_WIN32
1910
1911 #undef gdk_pixbuf_save
1912
1913 gboolean
1914 gdk_pixbuf_save (GdkPixbuf  *pixbuf, 
1915                  const char *filename, 
1916                  const char *type, 
1917                  GError    **error,
1918                  ...)
1919 {
1920         char *utf8_filename;
1921         gchar **keys = NULL;
1922         gchar **values = NULL;
1923         va_list args;
1924         gboolean result;
1925
1926         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1927         
1928         utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1929
1930         if (utf8_filename == NULL)
1931                 return FALSE;
1932
1933         va_start (args, error);
1934         
1935         collect_save_options (args, &keys, &values);
1936         
1937         va_end (args);
1938
1939         result = gdk_pixbuf_savev_utf8 (pixbuf, utf8_filename, type,
1940                                         keys, values,
1941                                         error);
1942
1943         g_free (utf8_filename);
1944
1945         g_strfreev (keys);
1946         g_strfreev (values);
1947
1948         return result;
1949 }
1950
1951 #endif
1952
1953 /**
1954  * gdk_pixbuf_savev:
1955  * @pixbuf: a #GdkPixbuf.
1956  * @filename: name of file to save.
1957  * @type: name of file format.
1958  * @option_keys: name of options to set, %NULL-terminated
1959  * @option_values: values for named options
1960  * @error: return location for error, or %NULL
1961  *
1962  * Saves pixbuf to a file in @type, which is currently "jpeg", "png", "tiff", "ico" or "bmp".
1963  * If @error is set, %FALSE will be returned. 
1964  * See gdk_pixbuf_save () for more details.
1965  *
1966  * Return value: whether an error was set
1967  **/
1968
1969 gboolean
1970 gdk_pixbuf_savev (GdkPixbuf  *pixbuf, 
1971                   const char *filename, 
1972                   const char *type,
1973                   char      **option_keys,
1974                   char      **option_values,
1975                   GError    **error)
1976 {
1977         FILE *f = NULL;
1978         gboolean result;
1979        
1980         g_return_val_if_fail (filename != NULL, FALSE);
1981         g_return_val_if_fail (type != NULL, FALSE);
1982         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1983        
1984         f = g_fopen (filename, "wb");
1985         
1986         if (f == NULL) {
1987                 gint save_errno = errno;
1988                 gchar *display_name = g_filename_display_name (filename);
1989                 g_set_error (error,
1990                              G_FILE_ERROR,
1991                              g_file_error_from_errno (save_errno),
1992                              _("Failed to open '%s' for writing: %s"),
1993                              display_name,
1994                              g_strerror (save_errno));
1995                 g_free (display_name);
1996                 return FALSE;
1997         }
1998
1999        
2000        result = gdk_pixbuf_real_save (pixbuf, f, type,
2001                                       option_keys, option_values,
2002                                       error);
2003        
2004        
2005        if (!result) {
2006                g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
2007                fclose (f);
2008                return FALSE;
2009        }
2010
2011        if (fclose (f) < 0) {
2012                gint save_errno = errno;
2013                gchar *display_name = g_filename_display_name (filename);
2014                g_set_error (error,
2015                             G_FILE_ERROR,
2016                             g_file_error_from_errno (save_errno),
2017                             _("Failed to close '%s' while writing image, all data may not have been saved: %s"),
2018                             display_name,
2019                             g_strerror (save_errno));
2020                g_free (display_name);
2021                return FALSE;
2022        }
2023        
2024        return TRUE;
2025 }
2026
2027 #ifdef G_OS_WIN32
2028
2029 #undef gdk_pixbuf_savev
2030
2031 gboolean
2032 gdk_pixbuf_savev (GdkPixbuf  *pixbuf, 
2033                   const char *filename, 
2034                   const char *type,
2035                   char      **option_keys,
2036                   char      **option_values,
2037                   GError    **error)
2038 {
2039         char *utf8_filename;
2040         gboolean retval;
2041
2042         g_return_val_if_fail (filename != NULL, FALSE);
2043        
2044         utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
2045
2046         if (utf8_filename == NULL)
2047                 return FALSE;
2048
2049         retval = gdk_pixbuf_savev_utf8 (pixbuf, utf8_filename, type,
2050                                         option_keys, option_values, error);
2051
2052         g_free (utf8_filename);
2053
2054         return retval;
2055 }
2056
2057 #endif
2058
2059 /**
2060  * gdk_pixbuf_save_to_callback:
2061  * @pixbuf: a #GdkPixbuf.
2062  * @save_func: a function that is called to save each block of data that
2063  *   the save routine generates.
2064  * @user_data: user data to pass to the save function.
2065  * @type: name of file format.
2066  * @error: return location for error, or %NULL
2067  * @Varargs: list of key-value save options
2068  *
2069  * Saves pixbuf in format @type by feeding the produced data to a 
2070  * callback. Can be used when you want to store the image to something 
2071  * other than a file, such as an in-memory buffer or a socket.  
2072  * If @error is set, %FALSE will be returned. Possible errors
2073  * include those in the #GDK_PIXBUF_ERROR domain and whatever the save
2074  * function generates.
2075  *
2076  * See gdk_pixbuf_save() for more details.
2077  *
2078  * Return value: whether an error was set
2079  *
2080  * Since: 2.4
2081  **/
2082 gboolean
2083 gdk_pixbuf_save_to_callback    (GdkPixbuf  *pixbuf,
2084                                 GdkPixbufSaveFunc save_func,
2085                                 gpointer user_data,
2086                                 const char *type, 
2087                                 GError    **error,
2088                                 ...)
2089 {
2090         gchar **keys = NULL;
2091         gchar **values = NULL;
2092         va_list args;
2093         gboolean result;
2094         
2095         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2096         
2097         va_start (args, error);
2098         
2099         collect_save_options (args, &keys, &values);
2100         
2101         va_end (args);
2102
2103         result = gdk_pixbuf_save_to_callbackv (pixbuf, save_func, user_data,
2104                                                type, keys, values,
2105                                                error);
2106
2107         g_strfreev (keys);
2108         g_strfreev (values);
2109
2110         return result;
2111 }
2112
2113 /**
2114  * gdk_pixbuf_save_to_callbackv:
2115  * @pixbuf: a #GdkPixbuf.
2116  * @save_func: a function that is called to save each block of data that
2117  *   the save routine generates.
2118  * @user_data: user data to pass to the save function.
2119  * @type: name of file format.
2120  * @option_keys: name of options to set, %NULL-terminated
2121  * @option_values: values for named options
2122  * @error: return location for error, or %NULL
2123  *
2124  * Saves pixbuf to a callback in format @type, which is currently "jpeg",
2125  * "png", "tiff", "ico" or "bmp".  If @error is set, %FALSE will be returned. See
2126  * gdk_pixbuf_save_to_callback () for more details.
2127  *
2128  * Return value: whether an error was set
2129  *
2130  * Since: 2.4
2131  **/
2132 gboolean
2133 gdk_pixbuf_save_to_callbackv   (GdkPixbuf  *pixbuf, 
2134                                 GdkPixbufSaveFunc save_func,
2135                                 gpointer user_data,
2136                                 const char *type,
2137                                 char      **option_keys,
2138                                 char      **option_values,
2139                                 GError    **error)
2140 {
2141         gboolean result;
2142         
2143        
2144         g_return_val_if_fail (save_func != NULL, FALSE);
2145         g_return_val_if_fail (type != NULL, FALSE);
2146         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2147        
2148        result = gdk_pixbuf_real_save_to_callback (pixbuf,
2149                                                   save_func, user_data, type,
2150                                                   option_keys, option_values,
2151                                                   error);
2152        
2153        if (!result) {
2154                g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
2155                return FALSE;
2156        }
2157
2158        return TRUE;
2159 }
2160
2161 /**
2162  * gdk_pixbuf_save_to_buffer:
2163  * @pixbuf: a #GdkPixbuf.
2164  * @buffer: location to receive a pointer to the new buffer.
2165  * @buffer_size: location to receive the size of the new buffer.
2166  * @type: name of file format.
2167  * @error: return location for error, or %NULL
2168  * @Varargs: list of key-value save options
2169  *
2170  * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
2171  * "png", "tiff", "ico" or "bmp".  This is a convenience function that uses
2172  * gdk_pixbuf_save_to_callback() to do the real work. Note that the buffer 
2173  * is not nul-terminated and may contain embedded  nuls.
2174  * If @error is set, %FALSE will be returned and @buffer will be set to
2175  * %NULL. Possible errors include those in the #GDK_PIXBUF_ERROR
2176  * domain.
2177  *
2178  * See gdk_pixbuf_save() for more details.
2179  *
2180  * Return value: whether an error was set
2181  *
2182  * Since: 2.4
2183  **/
2184 gboolean
2185 gdk_pixbuf_save_to_buffer      (GdkPixbuf  *pixbuf,
2186                                 gchar     **buffer,
2187                                 gsize      *buffer_size,
2188                                 const char *type, 
2189                                 GError    **error,
2190                                 ...)
2191 {
2192         gchar **keys = NULL;
2193         gchar **values = NULL;
2194         va_list args;
2195         gboolean result;
2196         
2197         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2198         
2199         va_start (args, error);
2200         
2201         collect_save_options (args, &keys, &values);
2202         
2203         va_end (args);
2204
2205         result = gdk_pixbuf_save_to_bufferv (pixbuf, buffer, buffer_size,
2206                                              type, keys, values,
2207                                              error);
2208
2209         g_strfreev (keys);
2210         g_strfreev (values);
2211
2212         return result;
2213 }
2214
2215 struct SaveToBufferData {
2216         gchar *buffer;
2217         gsize len, max;
2218 };
2219
2220 static gboolean
2221 save_to_buffer_callback (const gchar *data,
2222                          gsize count,
2223                          GError **error,
2224                          gpointer user_data)
2225 {
2226         struct SaveToBufferData *sdata = user_data;
2227         gchar *new_buffer;
2228         gsize new_max;
2229
2230         if (sdata->len + count > sdata->max) {
2231                 new_max = MAX (sdata->max*2, sdata->len + count);
2232                 new_buffer = g_try_realloc (sdata->buffer, new_max);
2233                 if (!new_buffer) {
2234                         g_set_error_literal (error,
2235                                              GDK_PIXBUF_ERROR,
2236                                              GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2237                                              _("Insufficient memory to save image into a buffer"));
2238                         return FALSE;
2239                 }
2240                 sdata->buffer = new_buffer;
2241                 sdata->max = new_max;
2242         }
2243         memcpy (sdata->buffer + sdata->len, data, count);
2244         sdata->len += count;
2245         return TRUE;
2246 }
2247
2248 /**
2249  * gdk_pixbuf_save_to_bufferv:
2250  * @pixbuf: a #GdkPixbuf.
2251  * @buffer: location to receive a pointer to the new buffer.
2252  * @buffer_size: location to receive the size of the new buffer.
2253  * @type: name of file format.
2254  * @option_keys: name of options to set, %NULL-terminated
2255  * @option_values: values for named options
2256  * @error: return location for error, or %NULL
2257  *
2258  * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
2259  * "tiff", "png", "ico" or "bmp".  See gdk_pixbuf_save_to_buffer() 
2260  * for more details.
2261  *
2262  * Return value: whether an error was set
2263  *
2264  * Since: 2.4
2265  **/
2266 gboolean
2267 gdk_pixbuf_save_to_bufferv     (GdkPixbuf  *pixbuf,
2268                                 gchar     **buffer,
2269                                 gsize      *buffer_size,
2270                                 const char *type, 
2271                                 char      **option_keys,
2272                                 char      **option_values,
2273                                 GError    **error)
2274 {
2275         static const gint initial_max = 1024;
2276         struct SaveToBufferData sdata;
2277
2278         *buffer = NULL;
2279         *buffer_size = 0;
2280
2281         sdata.buffer = g_try_malloc (initial_max);
2282         sdata.max = initial_max;
2283         sdata.len = 0;
2284         if (!sdata.buffer) {
2285                 g_set_error_literal (error,
2286                                      GDK_PIXBUF_ERROR,
2287                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2288                                      _("Insufficient memory to save image into a buffer"));
2289                 return FALSE;
2290         }
2291
2292         if (!gdk_pixbuf_save_to_callbackv (pixbuf,
2293                                            save_to_buffer_callback, &sdata,
2294                                            type, option_keys, option_values,
2295                                            error)) {
2296                 g_free (sdata.buffer);
2297                 return FALSE;
2298         }
2299
2300         *buffer = sdata.buffer;
2301         *buffer_size = sdata.len;
2302         return TRUE;
2303 }
2304
2305 typedef struct {
2306         GOutputStream *stream;
2307         GCancellable  *cancellable;
2308 } SaveToStreamData;
2309
2310 static gboolean
2311 save_to_stream (const gchar  *buffer,
2312                 gsize         count,
2313                 GError      **error,
2314                 gpointer      data)
2315 {
2316         SaveToStreamData *sdata = (SaveToStreamData *)data;
2317         gsize remaining;
2318         gssize written;
2319         GError *my_error = NULL;
2320
2321         remaining = count;
2322         written = 0;
2323         while (remaining > 0) {
2324                 buffer += written;
2325                 remaining -= written;
2326                 written = g_output_stream_write (sdata->stream, 
2327                                                  buffer, remaining, 
2328                                                  sdata->cancellable, 
2329                                                  &my_error);
2330                 if (written < 0) {
2331                         if (!my_error) {
2332                                 g_set_error_literal (error,
2333                                                      G_IO_ERROR, 0,
2334                                                      _("Error writing to image stream"));
2335                         }
2336                         else {
2337                                 g_propagate_error (error, my_error);
2338                         }
2339                         return FALSE;
2340                 }
2341         }
2342
2343         return TRUE;
2344 }
2345
2346 /** 
2347  * gdk_pixbuf_save_to_stream:
2348  * @pixbuf: a #GdkPixbuf
2349  * @stream: a #GOutputStream to save the pixbuf to
2350  * @type: name of file format
2351  * @cancellable: optional #GCancellable object, %NULL to ignore
2352  * @error: return location for error, or %NULL
2353  * @Varargs: list of key-value save options
2354  *
2355  * Saves @pixbuf to an output stream.
2356  *
2357  * Supported file formats are currently "jpeg", "tiff", "png", "ico" or 
2358  * "bmp". See gdk_pixbuf_save_to_buffer() for more details.
2359  *
2360  * The @cancellable can be used to abort the operation from another 
2361  * thread. If the operation was cancelled, the error %GIO_ERROR_CANCELLED 
2362  * will be returned. Other possible errors are in the #GDK_PIXBUF_ERROR 
2363  * and %G_IO_ERROR domains. 
2364  *
2365  * The stream is not closed.
2366  *
2367  * Returns: %TRUE if the pixbuf was saved successfully, %FALSE if an
2368  *     error was set.
2369  *
2370  * Since: 2.14
2371  */
2372 gboolean
2373 gdk_pixbuf_save_to_stream (GdkPixbuf      *pixbuf,
2374                            GOutputStream  *stream,
2375                            const char     *type,
2376                            GCancellable   *cancellable,
2377                            GError        **error,
2378                            ...)
2379 {
2380         gboolean res;
2381         gchar **keys = NULL;
2382         gchar **values = NULL;
2383         va_list args;
2384         SaveToStreamData data;
2385
2386         va_start (args, error);
2387         collect_save_options (args, &keys, &values);
2388         va_end (args);
2389
2390         data.stream = stream;
2391         data.cancellable = cancellable;
2392
2393         if (!gdk_pixbuf_save_to_callbackv (pixbuf, save_to_stream, 
2394                                            &data, type, 
2395                                            keys, values, 
2396                                            error)) {
2397                 error = NULL; /* Ignore further errors */
2398                 res = FALSE;
2399         }
2400
2401         g_strfreev (keys);
2402         g_strfreev (values);
2403
2404         return res;
2405 }
2406
2407 /**
2408  * gdk_pixbuf_format_get_name:
2409  * @format: a #GdkPixbufFormat
2410  *
2411  * Returns the name of the format.
2412  * 
2413  * Return value: the name of the format. 
2414  *
2415  * Since: 2.2
2416  */
2417 gchar *
2418 gdk_pixbuf_format_get_name (GdkPixbufFormat *format)
2419 {
2420         g_return_val_if_fail (format != NULL, NULL);
2421
2422         return g_strdup (format->name);
2423 }
2424
2425 /**
2426  * gdk_pixbuf_format_get_description:
2427  * @format: a #GdkPixbufFormat
2428  *
2429  * Returns a description of the format.
2430  * 
2431  * Return value: a description of the format.
2432  *
2433  * Since: 2.2
2434  */
2435 gchar *
2436 gdk_pixbuf_format_get_description (GdkPixbufFormat *format)
2437 {
2438         gchar *domain;
2439         gchar *description;
2440         g_return_val_if_fail (format != NULL, NULL);
2441
2442         if (format->domain != NULL) 
2443                 domain = format->domain;
2444         else 
2445                 domain = GETTEXT_PACKAGE;
2446         description = dgettext (domain, format->description);
2447
2448         return g_strdup (description);
2449 }
2450
2451 /**
2452  * gdk_pixbuf_format_get_mime_types:
2453  * @format: a #GdkPixbufFormat
2454  *
2455  * Returns the mime types supported by the format.
2456  * 
2457  * Return value: a %NULL-terminated array of mime types which must be freed with 
2458  * g_strfreev() when it is no longer needed.
2459  *
2460  * Since: 2.2
2461  */
2462 gchar **
2463 gdk_pixbuf_format_get_mime_types (GdkPixbufFormat *format)
2464 {
2465         g_return_val_if_fail (format != NULL, NULL);
2466
2467         return g_strdupv (format->mime_types);
2468 }
2469
2470 /**
2471  * gdk_pixbuf_format_get_extensions:
2472  * @format: a #GdkPixbufFormat
2473  *
2474  * Returns the filename extensions typically used for files in the 
2475  * given format.
2476  * 
2477  * Return value: a %NULL-terminated array of filename extensions which must be
2478  * freed with g_strfreev() when it is no longer needed.
2479  *
2480  * Since: 2.2
2481  */
2482 gchar **
2483 gdk_pixbuf_format_get_extensions (GdkPixbufFormat *format)
2484 {
2485         g_return_val_if_fail (format != NULL, NULL);
2486
2487         return g_strdupv (format->extensions);
2488 }
2489
2490 /**
2491  * gdk_pixbuf_format_is_writable:
2492  * @format: a #GdkPixbufFormat
2493  *
2494  * Returns whether pixbufs can be saved in the given format.
2495  * 
2496  * Return value: whether pixbufs can be saved in the given format.
2497  *
2498  * Since: 2.2
2499  */
2500 gboolean
2501 gdk_pixbuf_format_is_writable (GdkPixbufFormat *format)
2502 {
2503         g_return_val_if_fail (format != NULL, FALSE);
2504
2505         return (format->flags & GDK_PIXBUF_FORMAT_WRITABLE) != 0;
2506 }
2507
2508 /**
2509  * gdk_pixbuf_format_is_scalable:
2510  * @format: a #GdkPixbufFormat
2511  *
2512  * Returns whether this image format is scalable. If a file is in a 
2513  * scalable format, it is preferable to load it at the desired size, 
2514  * rather than loading it at the default size and scaling the 
2515  * resulting pixbuf to the desired size.
2516  * 
2517  * Return value: whether this image format is scalable.
2518  *
2519  * Since: 2.6
2520  */
2521 gboolean
2522 gdk_pixbuf_format_is_scalable (GdkPixbufFormat *format)
2523 {
2524         g_return_val_if_fail (format != NULL, FALSE);
2525
2526         return (format->flags & GDK_PIXBUF_FORMAT_SCALABLE) != 0;
2527 }
2528
2529 /**
2530  * gdk_pixbuf_format_is_disabled:
2531  * @format: a #GdkPixbufFormat
2532  *
2533  * Returns whether this image format is disabled. See
2534  * gdk_pixbuf_format_set_disabled().
2535  * 
2536  * Return value: whether this image format is disabled.
2537  *
2538  * Since: 2.6
2539  */
2540 gboolean   
2541 gdk_pixbuf_format_is_disabled (GdkPixbufFormat *format)
2542 {
2543         g_return_val_if_fail (format != NULL, FALSE);
2544
2545         return format->disabled;        
2546 }
2547
2548 /**
2549  * gdk_pixbuf_format_set_disabled:
2550  * @format: a #GdkPixbufFormat
2551  * @disabled: %TRUE to disable the format @format
2552  *
2553  * Disables or enables an image format. If a format is disabled, 
2554  * gdk-pixbuf won't use the image loader for this format to load 
2555  * images. Applications can use this to avoid using image loaders 
2556  * with an inappropriate license, see gdk_pixbuf_format_get_license().
2557  *
2558  * Since: 2.6
2559  */
2560 void 
2561 gdk_pixbuf_format_set_disabled (GdkPixbufFormat *format,
2562                                 gboolean         disabled)
2563 {
2564         g_return_if_fail (format != NULL);
2565         
2566         format->disabled = disabled != FALSE;
2567 }
2568
2569 /**
2570  * gdk_pixbuf_format_get_license:
2571  * @format: a #GdkPixbufFormat
2572  *
2573  * Returns information about the license of the image loader for the format. The
2574  * returned string should be a shorthand for a wellknown license, e.g. "LGPL",
2575  * "GPL", "QPL", "GPL/QPL", or "other" to indicate some other license.  This
2576  * string should be freed with g_free() when it's no longer needed.
2577  *
2578  * Returns: a string describing the license of @format. 
2579  *
2580  * Since: 2.6
2581  */
2582 gchar*
2583 gdk_pixbuf_format_get_license (GdkPixbufFormat *format)
2584 {
2585         g_return_val_if_fail (format != NULL, NULL);
2586
2587         return g_strdup (format->license);
2588 }
2589
2590 GdkPixbufFormat *
2591 _gdk_pixbuf_get_format (GdkPixbufModule *module)
2592 {
2593         g_return_val_if_fail (module != NULL, NULL);
2594
2595         return module->info;
2596 }
2597
2598 /**
2599  * gdk_pixbuf_get_formats:
2600  *
2601  * Obtains the available information about the image formats supported
2602  * by GdkPixbuf.
2603  *
2604  * Returns: A list of #GdkPixbufFormat<!-- -->s describing the supported 
2605  * image formats.  The list should be freed when it is no longer needed, 
2606  * but the structures themselves are owned by #GdkPixbuf and should not be 
2607  * freed.  
2608  *
2609  * Since: 2.2
2610  */
2611 GSList *
2612 gdk_pixbuf_get_formats (void)
2613 {
2614         GSList *result = NULL;
2615         GSList *modules;
2616
2617         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
2618                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
2619                 GdkPixbufFormat *info = _gdk_pixbuf_get_format (module);
2620                 result = g_slist_prepend (result, info);
2621         }
2622
2623         return result;
2624 }
2625
2626
2627 #define __GDK_PIXBUF_IO_C__
2628 #include "gdk-pixbuf-aliasdef.c"