]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/gdk-pixbuf-io.c
Fix many sparse warnings.
[~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 <glib.h>
31 #include <errno.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include "gdk-pixbuf-alias.h"
37 #include "gdk-pixbuf-private.h"
38 #include "gdk-pixbuf-io.h"
39
40 #ifdef G_OS_WIN32
41 #define STRICT
42 #include <windows.h>
43 #undef STRICT
44 #endif
45
46 static gint 
47 format_check (GdkPixbufModule *module, guchar *buffer, int size)
48 {
49         int j;
50         gchar m;
51         GdkPixbufModulePattern *pattern;
52
53         for (pattern = module->info->signature; pattern->prefix; pattern++) {
54                 for (j = 0; j < size && pattern->prefix[j] != 0; j++) {
55                         m = pattern->mask ? pattern->mask[j] : ' ';
56                         if (m == ' ') {
57                                 if (buffer[j] != pattern->prefix[j])
58                                         break;
59                         }
60                         else if (m == '!') {
61                                 if (buffer[j] == pattern->prefix[j])
62                                         break;
63                         }
64                         else if (m == 'z') {
65                                 if (buffer[j] != 0)
66                                         break;
67                         }
68                         else if (m == 'n') {
69                                 if (buffer[j] == 0)
70                                         break;
71                         }
72                 } 
73                 if (pattern->prefix[j] == 0) 
74                         return pattern->relevance;
75         }
76         return 0;
77 }
78
79 static GSList *file_formats = NULL;
80
81 static void gdk_pixbuf_io_init ();
82
83 static GSList *
84 get_file_formats (void)
85 {
86         if (file_formats == NULL)
87                 gdk_pixbuf_io_init ();
88         
89         return file_formats;
90 }
91
92
93 #ifdef USE_GMODULE 
94
95 static gboolean
96 scan_string (const char **pos, GString *out)
97 {
98         const char *p = *pos, *q = *pos;
99         char *tmp, *tmp2;
100         gboolean quoted;
101         
102         while (g_ascii_isspace (*p))
103                 p++;
104         
105         if (!*p)
106                 return FALSE;
107         else if (*p == '"') {
108                 p++;
109                 quoted = FALSE;
110                 for (q = p; (*q != '"') || quoted; q++) {
111                         if (!*q)
112                                 return FALSE;
113                         quoted = (*q == '\\') && !quoted;
114                 }
115                 
116                 tmp = g_strndup (p, q - p);
117                 tmp2 = g_strcompress (tmp);
118                 g_string_truncate (out, 0);
119                 g_string_append (out, tmp2);
120                 g_free (tmp);
121                 g_free (tmp2);
122         }
123         
124         q++;
125         *pos = q;
126         
127         return TRUE;
128 }
129
130 static gboolean
131 scan_int (const char **pos, int *out)
132 {
133         int i = 0;
134         char buf[32];
135         const char *p = *pos;
136         
137         while (g_ascii_isspace (*p))
138                 p++;
139         
140         if (*p < '0' || *p > '9')
141                 return FALSE;
142         
143         while ((*p >= '0') && (*p <= '9') && i < sizeof (buf)) {
144                 buf[i] = *p;
145                 i++;
146                 p++;
147         }
148         
149         if (i == sizeof (buf))
150                 return FALSE;
151         else
152                 buf[i] = '\0';
153         
154         *out = atoi (buf);
155         
156         *pos = p;
157
158         return TRUE;
159 }
160
161 static gboolean
162 skip_space (const char **pos)
163 {
164         const char *p = *pos;
165         
166         while (g_ascii_isspace (*p))
167                 p++;
168   
169         *pos = p;
170         
171         return !(*p == '\0');
172 }
173   
174 #ifdef G_OS_WIN32
175
176 /* DllMain function needed to tuck away the gdk-pixbuf DLL name */
177 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
178
179 static char *
180 get_toplevel (void)
181 {
182   static char *toplevel = NULL;
183
184   if (toplevel == NULL)
185     toplevel = g_win32_get_package_installation_subdirectory
186       (GETTEXT_PACKAGE, dll_name, "");
187
188   return toplevel;
189 }
190
191 static char *
192 get_sysconfdir (void)
193 {
194   static char *sysconfdir = NULL;
195
196   if (sysconfdir == NULL)
197     sysconfdir = g_win32_get_package_installation_subdirectory
198       (GETTEXT_PACKAGE, dll_name, "etc");
199
200   return sysconfdir;
201 }
202
203 #undef GTK_SYSCONFDIR
204 #define GTK_SYSCONFDIR get_sysconfdir()
205
206 static void
207 correct_prefix (gchar **path)
208 {
209   if (strncmp (*path, GTK_PREFIX "/", strlen (GTK_PREFIX "/")) == 0 ||
210       strncmp (*path, GTK_PREFIX "\\", strlen (GTK_PREFIX "\\")) == 0)
211     {
212       /* This is an entry put there by gdk-pixbuf-query-loaders on the
213        * packager's system. On Windows a prebuilt GTK+ package can be
214        * installed in a random location. The gdk-pixbuf.loaders file
215        * distributed in such a package contains paths from the package
216        * builder's machine. Replace the build-time prefix with the
217        * installation prefix on this machine.
218        */
219       gchar *tem = *path;
220       *path = g_strconcat (get_toplevel (), tem + strlen (GTK_PREFIX), NULL);
221       g_free (tem);
222     }
223 }
224
225 #endif
226
227 static gchar *
228 gdk_pixbuf_get_module_file (void)
229 {
230   gchar *result = g_strdup (g_getenv ("GDK_PIXBUF_MODULE_FILE"));
231
232   if (!result)
233           result = g_build_filename (GTK_SYSCONFDIR, "gtk-2.0", "gdk-pixbuf.loaders", NULL);
234
235   return result;
236 }
237
238 static void 
239 gdk_pixbuf_io_init (void)
240 {
241         GIOChannel *channel;
242         gchar *line_buf;
243         gsize term;
244         GString *tmp_buf = g_string_new (NULL);
245         gboolean have_error = FALSE;
246         GdkPixbufModule *module = NULL;
247         gchar *filename = gdk_pixbuf_get_module_file ();
248         int flags;
249         int n_patterns = 0;
250         GdkPixbufModulePattern *pattern;
251         GError *error = NULL;
252
253         channel = g_io_channel_new_file (filename, "r",  &error);
254         if (!channel) {
255                 g_warning ("Cannot open pixbuf loader module file '%s': %s",
256                            filename, error->message);
257                 return;
258         }
259         
260         while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL, &term, NULL) == G_IO_STATUS_NORMAL) {
261                 const char *p;
262                 
263                 p = line_buf;
264
265                 line_buf[term] = 0;
266
267                 if (!skip_space (&p)) {
268                                 /* Blank line marking the end of a module
269                                  */
270                         if (module && *p != '#') {
271 #ifdef G_OS_WIN32
272                                 correct_prefix (&module->module_path);
273 #endif
274                                 file_formats = g_slist_prepend (file_formats, module);
275                                 module = NULL;
276                         }
277                         
278                         goto next_line;
279                 }
280
281                 if (*p == '#') 
282                         goto next_line;
283                 
284                 if (!module) {
285                                 /* Read a module location
286                                  */
287                         module = g_new0 (GdkPixbufModule, 1);
288                         n_patterns = 0;
289                         
290                         if (!scan_string (&p, tmp_buf)) {
291                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
292                                            filename, line_buf);
293                                 have_error = TRUE;
294                         }
295                         module->module_path = g_strdup (tmp_buf->str);
296                 }
297                 else if (!module->module_name) {
298                         module->info = g_new0 (GdkPixbufFormat, 1);
299                         if (!scan_string (&p, tmp_buf)) {
300                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
301                                            filename, line_buf);
302                                 have_error = TRUE;
303                         }
304                         module->info->name =  g_strdup (tmp_buf->str);
305                         module->module_name = module->info->name;
306
307                         if (!scan_int (&p, &flags)) {
308                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
309                                            filename, line_buf);
310                                 have_error = TRUE;
311                         }
312                         module->info->flags = flags;
313                         
314                         if (!scan_string (&p, tmp_buf)) {
315                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
316                                            filename, line_buf);
317                                 have_error = TRUE;
318                         }                       
319                         if (tmp_buf->str[0] != 0)
320                                 module->info->domain = g_strdup (tmp_buf->str);
321
322                         if (!scan_string (&p, tmp_buf)) {
323                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
324                                            filename, line_buf);
325                                 have_error = TRUE;
326                         }                       
327                         module->info->description = g_strdup (tmp_buf->str);
328                 }
329                 else if (!module->info->mime_types) {
330                         int n = 1;
331                         module->info->mime_types = g_new0 (gchar*, 1);
332                         while (scan_string (&p, tmp_buf)) {
333                                 if (tmp_buf->str[0] != 0) {
334                                         module->info->mime_types =
335                                                 g_realloc (module->info->mime_types, (n + 1) * sizeof (gchar*));
336                                         module->info->mime_types[n - 1] = g_strdup (tmp_buf->str);
337                                         module->info->mime_types[n] = NULL;
338                                         n++;
339                                 }
340                         }
341                 }
342                 else if (!module->info->extensions) {
343                         int n = 1;
344                         module->info->extensions = g_new0 (gchar*, 1);
345                         while (scan_string (&p, tmp_buf)) {
346                                 if (tmp_buf->str[0] != 0) {
347                                         module->info->extensions =
348                                                 g_realloc (module->info->extensions, (n + 1) * sizeof (gchar*));
349                                         module->info->extensions[n - 1] = g_strdup (tmp_buf->str);
350                                         module->info->extensions[n] = NULL;
351                                         n++;
352                                 }
353                         }
354                 }
355                 else {
356                         n_patterns++;
357                         module->info->signature = (GdkPixbufModulePattern *)
358                                 g_realloc (module->info->signature, (n_patterns + 1) * sizeof (GdkPixbufModulePattern));
359                         pattern = module->info->signature + n_patterns;
360                         pattern->prefix = NULL;
361                         pattern->mask = NULL;
362                         pattern->relevance = 0;
363                         pattern--;
364                         if (!scan_string (&p, tmp_buf))
365                                 goto context_error;
366                         pattern->prefix = g_strdup (tmp_buf->str);
367                         
368                         if (!scan_string (&p, tmp_buf))
369                                 goto context_error;
370                         if (*tmp_buf->str)
371                                 pattern->mask = g_strdup (tmp_buf->str);
372                         else
373                                 pattern->mask = NULL;
374                         
375                         if (!scan_int (&p, &pattern->relevance))
376                                 goto context_error;
377                         
378                         goto next_line;
379
380                 context_error:
381                         g_free (pattern->prefix);
382                         g_free (pattern->mask);
383                         g_free (pattern);
384                         g_warning ("Error parsing loader info in '%s'\n  %s", 
385                                    filename, line_buf);
386                         have_error = TRUE;
387                 }
388         next_line:
389                 g_free (line_buf);
390         }
391         g_string_free (tmp_buf, TRUE);
392         g_io_channel_unref (channel);
393         g_free (filename);
394 }
395
396 /* actually load the image handler - gdk_pixbuf_get_module only get a */
397 /* reference to the module to load, it doesn't actually load it       */
398 /* perhaps these actions should be combined in one function           */
399 gboolean
400 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
401                          GError         **error)
402 {
403         char *path;
404         GModule *module;
405         gpointer sym;
406         
407         g_return_val_if_fail (image_module->module == NULL, FALSE);
408
409         path = image_module->module_path;
410         module = g_module_open (path, G_MODULE_BIND_LAZY);
411
412         if (!module) {
413                 g_set_error (error,
414                              GDK_PIXBUF_ERROR,
415                              GDK_PIXBUF_ERROR_FAILED,
416                              _("Unable to load image-loading module: %s: %s"),
417                              path, g_module_error ());
418                 return FALSE;
419         }
420
421         image_module->module = module;        
422         
423         if (g_module_symbol (module, "fill_vtable", &sym)) {
424                 GdkPixbufModuleFillVtableFunc func = (GdkPixbufModuleFillVtableFunc) sym;
425                 (* func) (image_module);
426                 return TRUE;
427         } else {
428                 g_set_error (error,
429                              GDK_PIXBUF_ERROR,
430                              GDK_PIXBUF_ERROR_FAILED,
431                              _("Image-loading module %s does not export the proper interface; perhaps it's from a different GTK version?"),
432                              path);
433                 return FALSE;
434         }
435 }
436 #else
437
438 #define module(type) \
439   extern void MODULE_ENTRY (type, fill_info)   (GdkPixbufFormat *info);   \
440   extern void MODULE_ENTRY (type, fill_vtable) (GdkPixbufModule *module)
441
442 module (png);
443 module (bmp);
444 module (wbmp);
445 module (gif);
446 module (ico);
447 module (ani);
448 module (jpeg);
449 module (pnm);
450 module (ras);
451 module (tiff);
452 module (xpm);
453 module (xbm);
454 module (tga);
455 module (pcx);
456
457 gboolean
458 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
459                          GError         **error)
460 {
461         GdkPixbufModuleFillInfoFunc fill_info = NULL;
462         GdkPixbufModuleFillVtableFunc fill_vtable = NULL;
463
464         image_module->module = (void *) 1;
465
466         if (FALSE) {
467                 /* Ugly hack so we can use else if unconditionally below ;-) */
468         }
469         
470 #ifdef INCLUDE_png      
471         else if (strcmp (image_module->module_name, "png") == 0) {
472                 fill_info = MODULE_ENTRY (png, fill_info);
473                 fill_vtable = MODULE_ENTRY (png, fill_vtable);
474         }
475 #endif
476
477 #ifdef INCLUDE_bmp      
478         else if (strcmp (image_module->module_name, "bmp") == 0) {
479                 fill_info = MODULE_ENTRY (bmp, fill_info);
480                 fill_vtable = MODULE_ENTRY (bmp, fill_vtable);
481         }
482 #endif
483
484 #ifdef INCLUDE_wbmp
485         else if (strcmp (image_module->module_name, "wbmp") == 0) {
486                 fill_info = MODULE_ENTRY (wbmp, fill_info);
487                 fill_vtable = MODULE_ENTRY (wbmp, fill_vtable);
488         }
489 #endif
490
491 #ifdef INCLUDE_gif
492         else if (strcmp (image_module->module_name, "gif") == 0) {
493                 fill_info = MODULE_ENTRY (gif, fill_info);
494                 fill_vtable = MODULE_ENTRY (gif, fill_vtable);
495         }
496 #endif
497
498 #ifdef INCLUDE_ico
499         else if (strcmp (image_module->module_name, "ico") == 0) {
500                 fill_info = MODULE_ENTRY (ico, fill_info);
501                 fill_vtable = MODULE_ENTRY (ico, fill_vtable);
502         }
503 #endif
504
505 #ifdef INCLUDE_ani
506         else if (strcmp (image_module->module_name, "ani") == 0) {
507                 fill_info = MODULE_ENTRY (ani, fill_info);
508                 fill_vtable = MODULE_ENTRY (ani, fill_vtable);
509         }
510 #endif
511
512 #ifdef INCLUDE_jpeg
513         else if (strcmp (image_module->module_name, "jpeg") == 0) {
514                 fill_info = MODULE_ENTRY (jpeg, fill_info);
515                 fill_vtable = MODULE_ENTRY (jpeg, fill_vtable);
516         }
517 #endif
518
519 #ifdef INCLUDE_pnm
520         else if (strcmp (image_module->module_name, "pnm") == 0) {
521                 fill_info = MODULE_ENTRY (pnm, fill_info);
522                 fill_vtable = MODULE_ENTRY (pnm, fill_vtable);
523         }
524 #endif
525
526 #ifdef INCLUDE_ras
527         else if (strcmp (image_module->module_name, "ras") == 0) {
528                 fill_info = MODULE_ENTRY (ras, fill_info);
529                 fill_vtable = MODULE_ENTRY (ras, fill_vtable);
530         }
531 #endif
532
533 #ifdef INCLUDE_tiff
534         else if (strcmp (image_module->module_name, "tiff") == 0) {
535                 fill_info = MODULE_ENTRY (tiff, fill_info);
536                 fill_vtable = MODULE_ENTRY (tiff, fill_vtable);
537         }
538 #endif
539
540 #ifdef INCLUDE_xpm
541         else if (strcmp (image_module->module_name, "xpm") == 0) {
542                 fill_info = MODULE_ENTRY (xpm, fill_info);
543                 fill_vtable = MODULE_ENTRY (xpm, fill_vtable);
544         }
545 #endif
546
547 #ifdef INCLUDE_xbm
548         else if (strcmp (image_module->module_name, "xbm") == 0) {
549                 fill_info = MODULE_ENTRY (xbm, fill_info);
550                 fill_vtable = MODULE_ENTRY (xbm, fill_vtable);
551         }
552 #endif
553
554 #ifdef INCLUDE_tga
555         else if (strcmp (image_module->module_name, "tga") == 0) {
556                 fill_info = MODULE_ENTRY (tga, fill_info);
557                 fill_vtable = MODULE_ENTRY (tga, fill_vtable);
558         }
559 #endif
560         
561 #ifdef INCLUDE_pcx
562         else if (strcmp (image_module->module_name, "pcx") == 0) {
563                 fill_info = MODULE_ENTRY (pcx, fill_info);
564                 fill_vtable = MODULE_ENTRY (pcx, fill_vtable);
565         }
566 #endif
567         
568         if (fill_vtable) {
569                 (* fill_vtable) (image_module);
570                 image_module->info = g_new0 (GdkPixbufFormat, 1);
571                 (* fill_info) (image_module->info);
572
573                 return TRUE;
574         } else {
575                 g_set_error (error,
576                              GDK_PIXBUF_ERROR,
577                              GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
578                              _("Image type '%s' is not supported"),
579                              image_module->module_name);
580
581                 return FALSE;
582         }
583 }
584
585 static void 
586 gdk_pixbuf_io_init ()
587 {
588         gchar *included_formats[] = { 
589                 "ani", "png", "bmp", "wbmp", "gif", 
590                 "ico", "jpeg", "pnm", "ras", "tiff", 
591                 "xpm", "xbm", "tga", "pcx",
592                 NULL
593         };
594         gchar **name;
595         GdkPixbufModule *module = NULL;
596         
597         for (name = included_formats; *name; name++) {
598                 module = g_new0 (GdkPixbufModule, 1);
599                 module->module_name = *name;
600                 if (_gdk_pixbuf_load_module (module, NULL))
601                         file_formats = g_slist_prepend (file_formats, module);
602                 else
603                         g_free (module);
604         }
605 }
606
607 #endif
608
609 \f
610
611 GdkPixbufModule *
612 _gdk_pixbuf_get_named_module (const char *name,
613                               GError **error)
614 {
615         GSList *modules;
616
617         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
618                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
619
620                 if (module->info->disabled)
621                         continue;
622
623                 if (!strcmp (name, module->module_name))
624                         return module;
625         }
626
627         g_set_error (error,
628                      GDK_PIXBUF_ERROR,
629                      GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
630                      _("Image type '%s' is not supported"),
631                      name);
632         
633         return NULL;
634 }
635
636 GdkPixbufModule *
637 _gdk_pixbuf_get_module (guchar *buffer, guint size,
638                         const gchar *filename,
639                         GError **error)
640 {
641         GSList *modules;
642
643         gint score, best = 0;
644         GdkPixbufModule *selected = NULL;
645         gchar *utf8_filename = NULL;
646
647         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
648                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
649
650                 if (module->info->disabled)
651                         continue;
652
653                 score = format_check (module, buffer, size);
654                 if (score > best) {
655                         best = score; 
656                         selected = module;
657                 }
658                 if (score >= 100) 
659                         break;
660         }
661         if (selected != NULL)
662                 return selected;
663
664         if (filename)
665                 utf8_filename = g_filename_to_utf8 (filename, -1,
666                                                     NULL, NULL, NULL);
667         
668         if (utf8_filename) {
669                 g_set_error (error,
670                              GDK_PIXBUF_ERROR,
671                              GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
672                              _("Couldn't recognize the image file format for file '%s'"),
673                              utf8_filename);
674                 g_free (utf8_filename);
675         }
676         else
677                 g_set_error (error,
678                              GDK_PIXBUF_ERROR,
679                              GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
680                              _("Unrecognized image file format"));
681
682
683         return NULL;
684 }
685
686
687 static void
688 prepared_notify (GdkPixbuf *pixbuf, 
689                  GdkPixbufAnimation *anim, 
690                  gpointer user_data)
691 {
692         if (pixbuf != NULL)
693                 g_object_ref (pixbuf);
694         *((GdkPixbuf **)user_data) = pixbuf;
695 }
696
697 GdkPixbuf *
698 _gdk_pixbuf_generic_image_load (GdkPixbufModule *module,
699                                 FILE *f,
700                                 GError **error)
701 {
702         guchar buffer[4096];
703         size_t length;
704         GdkPixbuf *pixbuf = NULL;
705         GdkPixbufAnimation *animation = NULL;
706         gpointer context;
707
708         if (module->load != NULL)
709                 return (* module->load) (f, error);
710         
711         if (module->begin_load != NULL) {
712                 
713                 context = module->begin_load (NULL, prepared_notify, NULL, &pixbuf, error);
714         
715                 if (!context)
716                         return NULL;
717                 
718                 while (!feof (f) && !ferror (f)) {
719                         length = fread (buffer, 1, sizeof (buffer), f);
720                         if (length > 0)
721                                 if (!module->load_increment (context, buffer, length, error)) {
722                                         module->stop_load (context, NULL);
723                                         if (pixbuf != NULL)
724                                                 g_object_unref (pixbuf);
725                                         return NULL;
726                                 }
727                 }
728                 
729                 if (!module->stop_load (context, error)) {
730                         if (pixbuf != NULL)
731                                 g_object_unref (pixbuf);
732                         return NULL;
733                 }
734                 
735                 return pixbuf;
736         }
737         
738         if (module->load_animation != NULL) {
739                 animation = (* module->load_animation) (f, error);
740                 if (animation != NULL) {
741                         pixbuf = gdk_pixbuf_animation_get_static_image (animation);
742
743                         g_object_ref (pixbuf);
744
745                         g_object_unref (animation);
746                         
747                         return pixbuf;
748                 }
749         }
750
751         return NULL;
752 }
753
754 /**
755  * gdk_pixbuf_new_from_file:
756  * @filename: Name of file to load.
757  * @error: Return location for an error
758  *
759  * Creates a new pixbuf by loading an image from a file.  The file format is
760  * detected automatically. If %NULL is returned, then @error will be set.
761  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
762  *
763  * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if
764  * any of several error conditions occurred:  the file could not be opened,
765  * there was no loader for the file's format, there was not enough memory to
766  * allocate the image buffer, or the image file contained invalid data.
767  **/
768 GdkPixbuf *
769 gdk_pixbuf_new_from_file (const char *filename,
770                           GError    **error)
771 {
772         GdkPixbuf *pixbuf;
773         int size;
774         FILE *f;
775         guchar buffer [128];
776         GdkPixbufModule *image_module;
777
778         g_return_val_if_fail (filename != NULL, NULL);
779         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
780
781         f = fopen (filename, "rb");
782         if (!f) {
783                 gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
784                                                            NULL, NULL, NULL);
785                 g_set_error (error,
786                              G_FILE_ERROR,
787                              g_file_error_from_errno (errno),
788                              _("Failed to open file '%s': %s"),
789                              utf8_filename ? utf8_filename : "???",
790                              g_strerror (errno));
791                 g_free (utf8_filename);
792                 return NULL;
793         }
794
795         size = fread (&buffer, 1, sizeof (buffer), f);
796         if (size == 0) {
797                 gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
798                                                            NULL, NULL, NULL);
799                 g_set_error (error,
800                              GDK_PIXBUF_ERROR,
801                              GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
802                              _("Image file '%s' contains no data"),
803                              utf8_filename ? utf8_filename : "???");
804                 g_free (utf8_filename);
805                 fclose (f);
806                 return NULL;
807         }
808
809         image_module = _gdk_pixbuf_get_module (buffer, size, filename, error);
810         if (image_module == NULL) {
811                 fclose (f);
812                 return NULL;
813         }
814
815         if (image_module->module == NULL)
816                 if (!_gdk_pixbuf_load_module (image_module, error)) {
817                         fclose (f);
818                         return NULL;
819                 }
820
821         fseek (f, 0, SEEK_SET);
822         pixbuf = _gdk_pixbuf_generic_image_load (image_module, f, error);
823         fclose (f);
824
825         if (pixbuf == NULL && error != NULL && *error == NULL) {
826
827                 /* I don't trust these crufty longjmp()'ing image libs
828                  * to maintain proper error invariants, and I don't
829                  * want user code to segfault as a result. We need to maintain
830                  * the invariant that error gets set if NULL is returned.
831                  */
832
833                 gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
834                                                            NULL, NULL, NULL);
835
836                 g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
837                 g_set_error (error,
838                              GDK_PIXBUF_ERROR,
839                              GDK_PIXBUF_ERROR_FAILED,
840                              _("Failed to load image '%s': reason not known, probably a corrupt image file"),
841                              utf8_filename ? utf8_filename : "???");
842                 g_free (utf8_filename);
843         } else if (error != NULL && *error != NULL) {
844
845           /* Add the filename to the error message */
846           GError *e = *error;
847           gchar  *old;
848           gchar  *utf8_filename = g_filename_to_utf8 (filename, -1,
849                                                       NULL, NULL, NULL);
850
851           old = e->message;
852
853           e->message = g_strdup_printf (_("Failed to load image '%s': %s"),
854                                         utf8_filename ? utf8_filename : "???",
855                                         old);
856
857           g_free (utf8_filename);
858           g_free (old);
859         }
860
861         return pixbuf;
862 }
863
864 static void
865 size_prepared_cb (GdkPixbufLoader *loader, 
866                   int              width,
867                   int              height,
868                   gpointer         data)
869 {
870         struct {
871                 gint width;
872                 gint height;
873                 gboolean preserve_aspect_ratio;
874         } *info = data;
875
876         g_return_if_fail (width > 0 && height > 0);
877
878         if(info->preserve_aspect_ratio) {
879                 if ((double)height * (double)info->width >
880                     (double)width * (double)info->height) {
881                         width = 0.5 + (double)width * (double)info->height / (double)height;
882                         height = info->height;
883                 } else {
884                         height = 0.5 + (double)height * (double)info->width / (double)width;
885                         width = info->width;
886                 }
887         } else {
888                 width = info->width;
889                 height = info->height;
890         }
891         
892         gdk_pixbuf_loader_set_size (loader, width, height);
893 }
894
895 /**
896  * gdk_pixbuf_new_from_file_at_scale:
897  * @filename: Name of file to load.
898  * @width: The width the image should have
899  * @height: The height the image should have
900  * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
901  * @error: Return location for an error
902  *
903  * Creates a new pixbuf by loading an image from a file.  The file format is
904  * detected automatically. If %NULL is returned, then @error will be set.
905  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
906  * The image will be scaled to fit in the requested size, optionally preserving
907  * the image's aspect ratio.
908  *
909  * Return value: A newly-created pixbuf with a reference count of 1, or %NULL 
910  * if any of several error conditions occurred:  the file could not be opened,
911  * there was no loader for the file's format, there was not enough memory to
912  * allocate the image buffer, or the image file contained invalid data.
913  *
914  * Since: 2.6
915  **/
916 GdkPixbuf *
917 gdk_pixbuf_new_from_file_at_scale (const char *filename,
918                                    int         width, 
919                                    int         height,
920                                    gboolean    preserve_aspect_ratio,
921                                    GError    **error)
922 {
923
924         GdkPixbufLoader *loader;
925         GdkPixbuf       *pixbuf;
926
927         guchar buffer [4096];
928         int length;
929         FILE *f;
930         struct {
931                 gint width;
932                 gint height;
933                 gboolean preserve_aspect_ratio;
934         } info;
935
936         g_return_val_if_fail (filename != NULL, NULL);
937         g_return_val_if_fail (width > 0 && height > 0, NULL);
938
939         f = fopen (filename, "rb");
940         if (!f) {
941                 gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
942                                                            NULL, NULL, NULL);
943                 g_set_error (error,
944                              G_FILE_ERROR,
945                              g_file_error_from_errno (errno),
946                              _("Failed to open file '%s': %s"),
947                              utf8_filename ? utf8_filename : "???",
948                              g_strerror (errno));
949                 g_free (utf8_filename);
950                 return NULL;
951         }
952
953         loader = gdk_pixbuf_loader_new ();
954
955         info.width = width;
956         info.height = height;
957         info.preserve_aspect_ratio = preserve_aspect_ratio;
958
959         g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info);
960
961         while (!feof (f) && !ferror (f)) {
962                 length = fread (buffer, 1, sizeof (buffer), f);
963                 if (length > 0)
964                         if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
965                                 gdk_pixbuf_loader_close (loader, NULL);
966                                 fclose (f);
967                                 g_object_unref (loader);
968                                 return NULL;
969                         }
970         }
971
972         fclose (f);
973
974         if (!gdk_pixbuf_loader_close (loader, error)) {
975                 g_object_unref (loader);
976                 return NULL;
977         }
978
979         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
980
981         if (!pixbuf) {
982                 gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
983                                                            NULL, NULL, NULL);
984
985                 g_object_unref (loader);
986
987                 g_set_error (error,
988                              GDK_PIXBUF_ERROR,
989                              GDK_PIXBUF_ERROR_FAILED,
990                              _("Failed to load image '%s': reason not known, probably a corrupt image file"),
991                              utf8_filename ? utf8_filename : "???");
992                 g_free (utf8_filename);
993                 return NULL;
994         }
995
996         g_object_ref (pixbuf);
997
998         g_object_unref (loader);
999
1000         return pixbuf;
1001 }
1002
1003 /**
1004  * gdk_pixbuf_new_from_file_at_size:
1005  * @filename: Name of file to load.
1006  * @width: The width the image should have
1007  * @height: The height the image should have
1008  * @error: Return location for an error
1009  *
1010  * Creates a new pixbuf by loading an image from a file.  The file format is
1011  * detected automatically. If %NULL is returned, then @error will be set.
1012  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
1013  * The image will be scaled to fit in the requested size, preserving
1014  * the image's aspect ratio.
1015  *
1016  * Return value: A newly-created pixbuf with a reference count of 1, or 
1017  * %NULL if any of several error conditions occurred:  the file could not 
1018  * be opened, there was no loader for the file's format, there was not 
1019  * enough memory to allocate the image buffer, or the image file contained 
1020  * invalid data.
1021  *
1022  * Since: 2.4
1023  **/
1024 GdkPixbuf *
1025 gdk_pixbuf_new_from_file_at_size (const char *filename,
1026                                   int         width, 
1027                                   int         height,
1028                                   GError    **error)
1029 {
1030         return gdk_pixbuf_new_from_file_at_scale (filename, 
1031                                                   width, height, 
1032                                                   TRUE, error);
1033 }
1034
1035 static void
1036 info_cb (GdkPixbufLoader *loader, 
1037          int              width,
1038          int              height,
1039          gpointer         data)
1040 {
1041         struct {
1042                 GdkPixbufFormat *format;
1043                 int width;
1044                 int height;
1045         } *info = data;
1046
1047         g_return_if_fail (width > 0 && height > 0);
1048
1049         info->format = gdk_pixbuf_loader_get_format (loader);
1050         info->width = width;
1051         info->height = height;
1052
1053         gdk_pixbuf_loader_set_size (loader, 0, 0);
1054 }
1055
1056 /**
1057  * gdk_pixbuf_get_file_info:
1058  * @filename: The name of the file to identify.
1059  * @width: Return location for the width of the image, or %NULL
1060  * @height: Return location for the height of the image, or %NULL
1061  * 
1062  * Parses an image file far enough to determine its format and size.
1063  * 
1064  * Returns: A #GdkPixbufFormat describing the image format of the file 
1065  *    or %NULL if the image format wasn't recognized. The return value 
1066  *    is owned by GdkPixbuf and should not be freed.
1067  *
1068  * Since: 2.4
1069  **/
1070 GdkPixbufFormat *
1071 gdk_pixbuf_get_file_info (const gchar  *filename,
1072                           gint         *width, 
1073                           gint         *height)
1074 {
1075         GdkPixbufLoader *loader;
1076         guchar buffer [4096];
1077         int length;
1078         FILE *f;
1079         struct {
1080                 GdkPixbufFormat *format;
1081                 gint width;
1082                 gint height;
1083         } info;
1084
1085         g_return_val_if_fail (filename != NULL, NULL);
1086
1087         f = fopen (filename, "rb");
1088         if (!f)
1089                 return NULL;
1090
1091         loader = gdk_pixbuf_loader_new ();
1092
1093         info.format = NULL;
1094         info.width = -1;
1095         info.height = -1;
1096                 
1097         g_signal_connect (loader, "size-prepared", G_CALLBACK (info_cb), &info);
1098
1099         while (!feof (f) && !ferror (f)) {
1100                 length = fread (buffer, 1, sizeof (buffer), f);
1101                 if (length > 0) {
1102                         if (!gdk_pixbuf_loader_write (loader, buffer, length, NULL))
1103                                 break;
1104                 }
1105                 if (info.format != NULL)
1106                         break;
1107         }
1108
1109         fclose (f);
1110         gdk_pixbuf_loader_close (loader, NULL);
1111         g_object_unref (loader);
1112
1113         if (width) 
1114                 *width = info.width;
1115         if (height) 
1116                 *height = info.height;
1117
1118         return info.format;
1119 }
1120
1121 /**
1122  * gdk_pixbuf_new_from_xpm_data:
1123  * @data: Pointer to inline XPM data.
1124  *
1125  * Creates a new pixbuf by parsing XPM data in memory.  This data is commonly
1126  * the result of including an XPM file into a program's C source.
1127  *
1128  * Return value: A newly-created pixbuf with a reference count of 1.
1129  **/
1130 GdkPixbuf *
1131 gdk_pixbuf_new_from_xpm_data (const char **data)
1132 {
1133         GdkPixbuf *(* load_xpm_data) (const char **data);
1134         GdkPixbuf *pixbuf;
1135         GError *error = NULL;
1136         GdkPixbufModule *xpm_module = _gdk_pixbuf_get_named_module ("xpm", &error);
1137         if (xpm_module == NULL) {
1138                 g_warning ("Error loading XPM image loader: %s", error->message);
1139                 g_error_free (error);
1140                 return NULL;
1141         }
1142
1143         if (xpm_module->module == NULL) {
1144                 if (!_gdk_pixbuf_load_module (xpm_module, &error)) {
1145                         g_warning ("Error loading XPM image loader: %s", error->message);
1146                         g_error_free (error);
1147                         return NULL;
1148                 }
1149         }
1150           
1151         if (xpm_module->load_xpm_data == NULL) {
1152                 g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
1153                 return NULL;
1154         } else
1155                 load_xpm_data = xpm_module->load_xpm_data;
1156
1157         pixbuf = (* load_xpm_data) (data);
1158         return pixbuf;
1159 }
1160
1161 static void
1162 collect_save_options (va_list   opts,
1163                       gchar  ***keys,
1164                       gchar  ***vals)
1165 {
1166   gchar *key;
1167   gchar *val;
1168   gchar *next;
1169   gint count;
1170
1171   count = 0;
1172   *keys = NULL;
1173   *vals = NULL;
1174   
1175   next = va_arg (opts, gchar*);
1176   while (next)
1177     {
1178       key = next;
1179       val = va_arg (opts, gchar*);
1180
1181       ++count;
1182
1183       /* woo, slow */
1184       *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
1185       *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
1186       
1187       (*keys)[count-1] = g_strdup (key);
1188       (*vals)[count-1] = g_strdup (val);
1189
1190       (*keys)[count] = NULL;
1191       (*vals)[count] = NULL;
1192       
1193       next = va_arg (opts, gchar*);
1194     }
1195 }
1196
1197 static gboolean
1198 save_to_file_callback (const gchar *buf,
1199                        gsize        count,
1200                        GError     **error,
1201                        gpointer     data)
1202 {
1203         FILE *filehandle = data;
1204         gsize n;
1205
1206         n = fwrite (buf, 1, count, filehandle);
1207         if (n != count) {
1208                 g_set_error (error,
1209                              G_FILE_ERROR,
1210                              g_file_error_from_errno (errno),
1211                              _("Error writing to image file: %s"),
1212                              g_strerror (errno));
1213                 return FALSE;
1214         }
1215         return TRUE;
1216 }
1217
1218 static gboolean
1219 gdk_pixbuf_real_save (GdkPixbuf     *pixbuf, 
1220                       FILE          *filehandle, 
1221                       const char    *type, 
1222                       gchar        **keys,
1223                       gchar        **values,
1224                       GError       **error)
1225 {
1226        GdkPixbufModule *image_module = NULL;       
1227
1228        image_module = _gdk_pixbuf_get_named_module (type, error);
1229
1230        if (image_module == NULL)
1231                return FALSE;
1232        
1233        if (image_module->module == NULL)
1234                if (!_gdk_pixbuf_load_module (image_module, error))
1235                        return FALSE;
1236
1237        if (image_module->save) {
1238                /* save normally */
1239                return (* image_module->save) (filehandle, pixbuf,
1240                                               keys, values,
1241                                               error);
1242        }
1243        else if (image_module->save_to_callback) {
1244                /* save with simple callback */
1245                return (* image_module->save_to_callback) (save_to_file_callback,
1246                                                           filehandle, pixbuf,
1247                                                           keys, values,
1248                                                           error);
1249        }
1250        else {
1251                /* can't save */
1252                g_set_error (error,
1253                             GDK_PIXBUF_ERROR,
1254                             GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
1255                             _("This build of gdk-pixbuf does not support saving the image format: %s"),
1256                             type);
1257                return FALSE;
1258        }
1259 }
1260
1261 #define TMP_FILE_BUF_SIZE 4096
1262
1263 static gboolean
1264 save_to_callback_with_tmp_file (GdkPixbufModule   *image_module,
1265                                 GdkPixbuf         *pixbuf,
1266                                 GdkPixbufSaveFunc  save_func,
1267                                 gpointer           user_data,
1268                                 gchar            **keys,
1269                                 gchar            **values,
1270                                 GError           **error)
1271 {
1272         int fd;
1273         FILE *f = NULL;
1274         gboolean retval = FALSE;
1275         gchar *buf = NULL;
1276         gsize n;
1277         gchar *filename = NULL;
1278
1279         buf = g_try_malloc (TMP_FILE_BUF_SIZE);
1280         if (buf == NULL) {
1281                 g_set_error (error,
1282                              GDK_PIXBUF_ERROR,
1283                              GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1284                              _("Insufficient memory to save image to callback"));
1285                 goto end;
1286         }
1287
1288         fd = g_file_open_tmp ("gdkpixbuf-save-tmp.XXXXXX", &filename, error);
1289         if (fd == -1)
1290                 goto end;
1291         f = fdopen (fd, "wb+");
1292         if (f == NULL) {
1293                 g_set_error (error,
1294                              G_FILE_ERROR,
1295                              g_file_error_from_errno (errno),
1296                              _("Failed to open temporary file"));
1297                 goto end;
1298         }
1299         if (!(* image_module->save) (f, pixbuf, keys, values, error))
1300                 goto end;
1301         rewind (f);
1302         for (;;) {
1303                 n = fread (buf, 1, TMP_FILE_BUF_SIZE, f);
1304                 if (n > 0) {
1305                         if (!save_func (buf, n, error, user_data))
1306                                 goto end;
1307                 }
1308                 if (n != TMP_FILE_BUF_SIZE) 
1309                         break;
1310         }
1311         if (ferror (f)) {
1312                 g_set_error (error,
1313                              G_FILE_ERROR,
1314                              g_file_error_from_errno (errno),
1315                              _("Failed to read from temporary file"));
1316                 goto end;
1317         }
1318         retval = TRUE;
1319
1320  end:
1321         /* cleanup and return retval */
1322         if (f)
1323                 fclose (f);
1324         if (filename) {
1325                 unlink (filename);
1326                 g_free (filename);
1327         }
1328         g_free (buf);
1329
1330         return retval;
1331 }
1332
1333 static gboolean
1334 gdk_pixbuf_real_save_to_callback (GdkPixbuf         *pixbuf,
1335                                   GdkPixbufSaveFunc  save_func,
1336                                   gpointer           user_data,
1337                                   const char        *type, 
1338                                   gchar            **keys,
1339                                   gchar            **values,
1340                                   GError           **error)
1341 {
1342        GdkPixbufModule *image_module = NULL;       
1343
1344        image_module = _gdk_pixbuf_get_named_module (type, error);
1345
1346        if (image_module == NULL)
1347                return FALSE;
1348        
1349        if (image_module->module == NULL)
1350                if (!_gdk_pixbuf_load_module (image_module, error))
1351                        return FALSE;
1352
1353        if (image_module->save_to_callback) {
1354                /* save normally */
1355                return (* image_module->save_to_callback) (save_func, user_data, 
1356                                                           pixbuf, keys, values,
1357                                                           error);
1358        }
1359        else if (image_module->save) {
1360                /* use a temporary file */
1361                return save_to_callback_with_tmp_file (image_module, pixbuf,
1362                                                       save_func, user_data, 
1363                                                       keys, values,
1364                                                       error);
1365        }
1366        else {
1367                /* can't save */
1368                g_set_error (error,
1369                             GDK_PIXBUF_ERROR,
1370                             GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
1371                             _("This build of gdk-pixbuf does not support saving the image format: %s"),
1372                             type);
1373                return FALSE;
1374        }
1375 }
1376
1377  
1378 /**
1379  * gdk_pixbuf_save:
1380  * @pixbuf: a #GdkPixbuf.
1381  * @filename: name of file to save.
1382  * @type: name of file format.
1383  * @error: return location for error, or %NULL
1384  * @Varargs: list of key-value save options
1385  *
1386  * Saves pixbuf to a file in format @type. By default, "jpeg", "png" and 
1387  * "ico" are possible file formats to save in, but more formats may be
1388  * installed. The list of all writable formats can be determined in the 
1389  * following way:
1390  *
1391  * <informalexample><programlisting>
1392  * void add_if_writable (GdkPixbufFormat *data, GSList **list)
1393  * {
1394  *   if (gdk_pixbuf_format_is_writable (data))
1395  *     *list = g_slist_prepend (*list, data);
1396  * }
1397  * <!-- -->
1398  * GSList *formats = gdk_pixbuf_get_formats (<!-- -->);
1399  * GSList *writable_formats = NULL;
1400  * g_slist_foreach (formats, add_if_writable, &amp;writable_formats);
1401  * g_slist_free (formats);
1402  * </programlisting></informalexample>
1403  *
1404  * If @error is set, %FALSE will be returned. Possible errors include 
1405  * those in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
1406  *
1407  * The variable argument list should be %NULL-terminated; if not empty,
1408  * it should contain pairs of strings that modify the save
1409  * parameters. For example:
1410  * <informalexample><programlisting>
1411  * gdk_pixbuf_save (pixbuf, handle, "jpeg", &amp;error,
1412  *                  "quality", "100", NULL);
1413  * </programlisting></informalexample>
1414  *
1415  * Currently only few parameters exist. JPEG images can be saved with a 
1416  * "quality" parameter; its value should be in the range [0,100]. 
1417  * Text chunks can be attached to PNG images by specifying parameters of
1418  * the form "tEXt::key", where key is an ASCII string of length 1-79.
1419  * The values are UTF-8 encoded strings. 
1420  * ICO images can be saved in depth 16, 24, or 32, by using the "depth"
1421  * parameter. When the ICO saver is given "x_hot" and "y_hot" parameters,
1422  * it produces a CUR instead of an ICO.
1423  *
1424  * Return value: whether an error was set
1425  **/
1426
1427 gboolean
1428 gdk_pixbuf_save (GdkPixbuf  *pixbuf, 
1429                  const char *filename, 
1430                  const char *type, 
1431                  GError    **error,
1432                  ...)
1433 {
1434         gchar **keys = NULL;
1435         gchar **values = NULL;
1436         va_list args;
1437         gboolean result;
1438
1439         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1440         
1441         va_start (args, error);
1442         
1443         collect_save_options (args, &keys, &values);
1444         
1445         va_end (args);
1446
1447         result = gdk_pixbuf_savev (pixbuf, filename, type,
1448                                    keys, values,
1449                                    error);
1450
1451         g_strfreev (keys);
1452         g_strfreev (values);
1453
1454         return result;
1455 }
1456
1457 /**
1458  * gdk_pixbuf_savev:
1459  * @pixbuf: a #GdkPixbuf.
1460  * @filename: name of file to save.
1461  * @type: name of file format.
1462  * @option_keys: name of options to set, %NULL-terminated
1463  * @option_values: values for named options
1464  * @error: return location for error, or %NULL
1465  *
1466  * Saves pixbuf to a file in @type, which is currently "jpeg", "png" or "ico".
1467  * If @error is set, %FALSE will be returned. 
1468  * See gdk_pixbuf_save () for more details.
1469  *
1470  * Return value: whether an error was set
1471  **/
1472
1473 gboolean
1474 gdk_pixbuf_savev (GdkPixbuf  *pixbuf, 
1475                   const char *filename, 
1476                   const char *type,
1477                   char      **option_keys,
1478                   char      **option_values,
1479                   GError    **error)
1480 {
1481         FILE *f = NULL;
1482         gboolean result;
1483         
1484        
1485         g_return_val_if_fail (filename != NULL, FALSE);
1486         g_return_val_if_fail (type != NULL, FALSE);
1487         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1488        
1489         f = fopen (filename, "wb");
1490         
1491         if (f == NULL) {
1492                 gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
1493                                                            NULL, NULL, NULL);
1494                 g_set_error (error,
1495                              G_FILE_ERROR,
1496                              g_file_error_from_errno (errno),
1497                              _("Failed to open '%s' for writing: %s"),
1498                              utf8_filename ? utf8_filename : "???",
1499                              g_strerror (errno));
1500                 g_free (utf8_filename);
1501                 return FALSE;
1502         }
1503
1504        
1505        result = gdk_pixbuf_real_save (pixbuf, f, type,
1506                                       option_keys, option_values,
1507                                       error);
1508        
1509        
1510        if (!result) {
1511                g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
1512                fclose (f);
1513                return FALSE;
1514        }
1515
1516        if (fclose (f) < 0) {
1517                gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
1518                                                            NULL, NULL, NULL);
1519                g_set_error (error,
1520                             G_FILE_ERROR,
1521                             g_file_error_from_errno (errno),
1522                             _("Failed to close '%s' while writing image, all data may not have been saved: %s"),
1523                             utf8_filename ? utf8_filename : "???",
1524                             g_strerror (errno));
1525                g_free (utf8_filename);
1526                return FALSE;
1527        }
1528        
1529        return TRUE;
1530 }
1531
1532 /**
1533  * gdk_pixbuf_save_to_callback:
1534  * @pixbuf: a #GdkPixbuf.
1535  * @save_func: a function that is called to save each block of data that
1536  *   the save routine generates.
1537  * @user_data: user data to pass to the save function.
1538  * @type: name of file format.
1539  * @error: return location for error, or %NULL
1540  * @Varargs: list of key-value save options
1541  *
1542  * Saves pixbuf in format @type by feeding the produced data to a 
1543  * callback. Can be used when you want to store the image to something 
1544  * other than a file, such as an in-memory buffer or a socket.  
1545  * If @error is set, %FALSE will be returned. Possible errors
1546  * include those in the #GDK_PIXBUF_ERROR domain and whatever the save
1547  * function generates.
1548  *
1549  * See gdk_pixbuf_save() for more details.
1550  *
1551  * Return value: whether an error was set
1552  *
1553  * Since: 2.4
1554  **/
1555 gboolean
1556 gdk_pixbuf_save_to_callback    (GdkPixbuf  *pixbuf,
1557                                 GdkPixbufSaveFunc save_func,
1558                                 gpointer user_data,
1559                                 const char *type, 
1560                                 GError    **error,
1561                                 ...)
1562 {
1563         gchar **keys = NULL;
1564         gchar **values = NULL;
1565         va_list args;
1566         gboolean result;
1567         
1568         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1569         
1570         va_start (args, error);
1571         
1572         collect_save_options (args, &keys, &values);
1573         
1574         va_end (args);
1575
1576         result = gdk_pixbuf_save_to_callbackv (pixbuf, save_func, user_data,
1577                                                type, keys, values,
1578                                                error);
1579
1580         g_strfreev (keys);
1581         g_strfreev (values);
1582
1583         return result;
1584 }
1585
1586 /**
1587  * gdk_pixbuf_save_to_callbackv:
1588  * @pixbuf: a #GdkPixbuf.
1589  * @save_func: a function that is called to save each block of data that
1590  *   the save routine generates.
1591  * @user_data: user data to pass to the save function.
1592  * @type: name of file format.
1593  * @option_keys: name of options to set, %NULL-terminated
1594  * @option_values: values for named options
1595  * @error: return location for error, or %NULL
1596  *
1597  * Saves pixbuf to a callback in format @type, which is currently "jpeg",
1598  * "png" or "ico".  If @error is set, %FALSE will be returned. See
1599  * gdk_pixbuf_save_to_callback () for more details.
1600  *
1601  * Return value: whether an error was set
1602  *
1603  * Since: 2.4
1604  **/
1605 gboolean
1606 gdk_pixbuf_save_to_callbackv   (GdkPixbuf  *pixbuf, 
1607                                 GdkPixbufSaveFunc save_func,
1608                                 gpointer user_data,
1609                                 const char *type,
1610                                 char      **option_keys,
1611                                 char      **option_values,
1612                                 GError    **error)
1613 {
1614         gboolean result;
1615         
1616        
1617         g_return_val_if_fail (save_func != NULL, FALSE);
1618         g_return_val_if_fail (type != NULL, FALSE);
1619         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1620        
1621        result = gdk_pixbuf_real_save_to_callback (pixbuf,
1622                                                   save_func, user_data, type,
1623                                                   option_keys, option_values,
1624                                                   error);
1625        
1626        if (!result) {
1627                g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
1628                return FALSE;
1629        }
1630
1631        return TRUE;
1632 }
1633
1634 /**
1635  * gdk_pixbuf_save_to_buffer:
1636  * @pixbuf: a #GdkPixbuf.
1637  * @buffer: location to receive a pointer to the new buffer.
1638  * @buffer_size: location to receive the size of the new buffer.
1639  * @type: name of file format.
1640  * @error: return location for error, or %NULL
1641  * @Varargs: list of key-value save options
1642  *
1643  * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
1644  * "png" or "ico".  This is a convenience function that uses
1645  * gdk_pixbuf_save_to_callback() to do the real work. Note that the buffer 
1646  * is not nul-terminated and may contain embedded  nuls.
1647  * If @error is set, %FALSE will be returned and @string will be set to
1648  * %NULL. Possible errors include those in the #GDK_PIXBUF_ERROR
1649  * domain.
1650  *
1651  * See gdk_pixbuf_save() for more details.
1652  *
1653  * Return value: whether an error was set
1654  *
1655  * Since: 2.4
1656  **/
1657 gboolean
1658 gdk_pixbuf_save_to_buffer      (GdkPixbuf  *pixbuf,
1659                                 gchar     **buffer,
1660                                 gsize      *buffer_size,
1661                                 const char *type, 
1662                                 GError    **error,
1663                                 ...)
1664 {
1665         gchar **keys = NULL;
1666         gchar **values = NULL;
1667         va_list args;
1668         gboolean result;
1669         
1670         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1671         
1672         va_start (args, error);
1673         
1674         collect_save_options (args, &keys, &values);
1675         
1676         va_end (args);
1677
1678         result = gdk_pixbuf_save_to_bufferv (pixbuf, buffer, buffer_size,
1679                                              type, keys, values,
1680                                              error);
1681
1682         g_strfreev (keys);
1683         g_strfreev (values);
1684
1685         return result;
1686 }
1687
1688 struct SaveToBufferData {
1689         gchar *buffer;
1690         gsize len, max;
1691 };
1692
1693 static gboolean
1694 save_to_buffer_callback (const gchar *data,
1695                          gsize count,
1696                          GError **error,
1697                          gpointer user_data)
1698 {
1699         struct SaveToBufferData *sdata = user_data;
1700         gchar *new_buffer;
1701         gsize new_max;
1702
1703         if (sdata->len + count > sdata->max) {
1704                 new_max = MAX (sdata->max*2, sdata->len + count);
1705                 new_buffer = g_try_realloc (sdata->buffer, new_max);
1706                 if (!new_buffer) {
1707                         g_set_error (error,
1708                                      GDK_PIXBUF_ERROR,
1709                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1710                                      _("Insufficient memory to save image into a buffer"));
1711                         return FALSE;
1712                 }
1713                 sdata->buffer = new_buffer;
1714                 sdata->max = new_max;
1715         }
1716         memcpy (sdata->buffer + sdata->len, data, count);
1717         sdata->len += count;
1718         return TRUE;
1719 }
1720
1721 /**
1722  * gdk_pixbuf_save_to_bufferv:
1723  * @pixbuf: a #GdkPixbuf.
1724  * @buffer: location to receive a pointer to the new buffer.
1725  * @buffer_size: location to receive the size of the new buffer.
1726  * @type: name of file format.
1727  * @option_keys: name of options to set, %NULL-terminated
1728  * @option_values: values for named options
1729  * @error: return location for error, or %NULL
1730  *
1731  * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
1732  * "png" or "ico".  See gdk_pixbuf_save_to_buffer() for more details.
1733  *
1734  * Return value: whether an error was set
1735  *
1736  * Since: 2.4
1737  **/
1738 gboolean
1739 gdk_pixbuf_save_to_bufferv     (GdkPixbuf  *pixbuf,
1740                                 gchar     **buffer,
1741                                 gsize      *buffer_size,
1742                                 const char *type, 
1743                                 char      **option_keys,
1744                                 char      **option_values,
1745                                 GError    **error)
1746 {
1747         static const gint initial_max = 1024;
1748         struct SaveToBufferData sdata;
1749
1750         *buffer = NULL;
1751         *buffer_size = 0;
1752
1753         sdata.buffer = g_try_malloc (initial_max);
1754         sdata.max = initial_max;
1755         sdata.len = 0;
1756         if (!sdata.buffer) {
1757                 g_set_error (error,
1758                              GDK_PIXBUF_ERROR,
1759                              GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1760                              _("Insufficient memory to save image into a buffer"));
1761                 return FALSE;
1762         }
1763
1764         if (!gdk_pixbuf_save_to_callbackv (pixbuf,
1765                                            save_to_buffer_callback, &sdata,
1766                                            type, option_keys, option_values,
1767                                            error)) {
1768                 g_free (sdata.buffer);
1769                 return FALSE;
1770         }
1771
1772         *buffer = sdata.buffer;
1773         *buffer_size = sdata.len;
1774         return TRUE;
1775 }
1776
1777 /**
1778  * gdk_pixbuf_format_get_name:
1779  * @format: a #GdkPixbufFormat
1780  *
1781  * Returns the name of the format.
1782  * 
1783  * Return value: the name of the format. 
1784  *
1785  * Since: 2.2
1786  */
1787 gchar *
1788 gdk_pixbuf_format_get_name (GdkPixbufFormat *format)
1789 {
1790         g_return_val_if_fail (format != NULL, NULL);
1791
1792         return g_strdup (format->name);
1793 }
1794
1795 /**
1796  * gdk_pixbuf_format_get_description:
1797  * @format: a #GdkPixbufFormat
1798  *
1799  * Returns a description of the format.
1800  * 
1801  * Return value: a description of the format.
1802  *
1803  * Since: 2.2
1804  */
1805 gchar *
1806 gdk_pixbuf_format_get_description (GdkPixbufFormat *format)
1807 {
1808         gchar *domain;
1809         gchar *description;
1810         g_return_val_if_fail (format != NULL, NULL);
1811
1812         if (format->domain != NULL) 
1813                 domain = format->domain;
1814         else 
1815                 domain = GETTEXT_PACKAGE;
1816         description = dgettext (domain, format->description);
1817
1818         return g_strdup (description);
1819 }
1820
1821 /**
1822  * gdk_pixbuf_format_get_mime_types:
1823  * @format: a #GdkPixbufFormat
1824  *
1825  * Returns the mime types supported by the format.
1826  * 
1827  * Return value: a %NULL-terminated array of mime types which must be freed with 
1828  * g_strfreev() when it is no longer needed.
1829  *
1830  * Since: 2.2
1831  */
1832 gchar **
1833 gdk_pixbuf_format_get_mime_types (GdkPixbufFormat *format)
1834 {
1835         g_return_val_if_fail (format != NULL, NULL);
1836
1837         return g_strdupv (format->mime_types);
1838 }
1839
1840 /**
1841  * gdk_pixbuf_format_get_extensions:
1842  * @format: a #GdkPixbufFormat
1843  *
1844  * Returns the filename extensions typically used for files in the 
1845  * given format.
1846  * 
1847  * Return value: a %NULL-terminated array of filename extensions which must be
1848  * freed with g_strfreev() when it is no longer needed.
1849  *
1850  * Since: 2.2
1851  */
1852 gchar **
1853 gdk_pixbuf_format_get_extensions (GdkPixbufFormat *format)
1854 {
1855         g_return_val_if_fail (format != NULL, NULL);
1856
1857         return g_strdupv (format->extensions);
1858 }
1859
1860 /**
1861  * gdk_pixbuf_format_is_writable:
1862  * @format: a #GdkPixbufFormat
1863  *
1864  * Returns whether pixbufs can be saved in the given format.
1865  * 
1866  * Return value: whether pixbufs can be saved in the given format.
1867  *
1868  * Since: 2.2
1869  */
1870 gboolean
1871 gdk_pixbuf_format_is_writable (GdkPixbufFormat *format)
1872 {
1873         g_return_val_if_fail (format != NULL, FALSE);
1874
1875         return (format->flags & GDK_PIXBUF_FORMAT_WRITABLE) != 0;
1876 }
1877
1878 /**
1879  * gdk_pixbuf_format_is_scalable:
1880  * @format: a #GdkPixbufFormat
1881  *
1882  * Returns whether this image format is scalable. If a file is in a 
1883  * scalable format, it is preferable to load it at the desired size, 
1884  * rather than loading it at the default size and scaling the 
1885  * resulting pixbuf to the desired size.
1886  * 
1887  * Return value: whether this image format is scalable.
1888  *
1889  * Since: 2.6
1890  */
1891 gboolean
1892 gdk_pixbuf_format_is_scalable (GdkPixbufFormat *format)
1893 {
1894         g_return_val_if_fail (format != NULL, FALSE);
1895
1896         return (format->flags & GDK_PIXBUF_FORMAT_SCALABLE) != 0;
1897 }
1898
1899 /**
1900  * gdk_pixbuf_format_is_disabled:
1901  * @format: a #GdkPixbufFormat
1902  *
1903  * Returns whether this image format is disabled. See
1904  * gdk_pixbuf_format_set_disabled().
1905  * 
1906  * Return value: whether this image format is disabled.
1907  *
1908  * Since: 2.6
1909  */
1910 gboolean   
1911 gdk_pixbuf_format_is_disabled (GdkPixbufFormat *format)
1912 {
1913         g_return_val_if_fail (format != NULL, FALSE);
1914
1915         return format->disabled;        
1916 }
1917
1918 /**
1919  * gdk_pixbuf_format_set_disabled:
1920  * @format: a #GdkPixbufFormat
1921  * @disabled: %TRUE to disable the format @format
1922  *
1923  * Disables or enables an image format. If a format is disabled, 
1924  * gdk-pixbuf won't use the image loader for this format to load 
1925  * images. Applications can use this to avoid using image loaders 
1926  * with an inappropriate license, see gdk_pixbuf_format_get_license().
1927  *
1928  * Since: 2.6
1929  */
1930 void 
1931 gdk_pixbuf_format_set_disabled (GdkPixbufFormat *format,
1932                                 gboolean         disabled)
1933 {
1934         g_return_if_fail (format != NULL);
1935         
1936         format->disabled = disabled != FALSE;
1937 }
1938
1939 /**
1940  * gdk_pixbuf_format_get_license:
1941  * @format: a #GdkPixbufFormat
1942  *
1943  * Returns information about the license of the image loader
1944  * for the format. The returned string should be a shorthand for 
1945  * a wellknown license, e.g. "LGPL", "GPL", "QPL", "GPL/QPL",
1946  * or "other" to indicate some other license.  
1947  *
1948  * Returns: a string describing the license of @format. 
1949  *
1950  * Since: 2.6
1951  */
1952 gchar*
1953 gdk_pixbuf_format_get_license (GdkPixbufFormat *format)
1954 {
1955         g_return_val_if_fail (format != NULL, NULL);
1956
1957         return g_strdup (format->license);
1958 }
1959
1960 GdkPixbufFormat *
1961 _gdk_pixbuf_get_format (GdkPixbufModule *module)
1962 {
1963         g_return_val_if_fail (module != NULL, NULL);
1964
1965         return module->info;
1966 }
1967
1968 /**
1969  * gdk_pixbuf_get_formats:
1970  *
1971  * Obtains the available information about the image formats supported
1972  * by GdkPixbuf.
1973  *
1974  * Returns: A list of #GdkPixbufFormat<!-- -->s describing the supported 
1975  * image formats.  The list should be freed when it is no longer needed, 
1976  * but the structures themselves are owned by #GdkPixbuf and should not be 
1977  * freed.  
1978  *
1979  * Since: 2.2
1980  */
1981 GSList *
1982 gdk_pixbuf_get_formats (void)
1983 {
1984         GSList *result = NULL;
1985         GSList *modules;
1986
1987         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
1988                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
1989                 GdkPixbufFormat *info = _gdk_pixbuf_get_format (module);
1990                 result = g_slist_prepend (result, info);
1991         }
1992
1993         return result;
1994 }
1995
1996
1997
1998
1999