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