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