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