1 /* GdkPixbuf library - Main loading interface.
2 *
3 * Copyright (C) 1999 The Free Software Foundation
4 *
5 * Authors: Miguel de Icaza <miguel@gnu.org>
6 * Federico Mena-Quintero <federico@gimp.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31
32 #include <glib.h>
33 #include <gio/gio.h>
34
35 #include "gdk-pixbuf-private.h"
36 #include "gdk-pixbuf-loader.h"
37 #include "gdk-pixdata.h"
38
39 #include <glib/gstdio.h>
40
41 #ifdef G_OS_WIN32
42 #define STRICT
43 #include <windows.h>
44 #undef STRICT
45 #endif
46 #ifdef OS_DARWIN
47 #include <mach-o/dyld.h>
48 #endif
49
50 /**
51 * SECTION:file-loading
52 * @Short_description: Loading a pixbuf from a file.
53 * @Title: File Loading
54 * @See_also: #GdkPixbufLoader.
55 *
56 * The GdkPixBuf library provides a simple mechanism for loading
57 * an image from a file in synchronous fashion. This means that the
58 * library takes control of the application while the file is being
59 * loaded; from the user's point of view, the application will block
60 * until the image is done loading.
61 *
62 *
63 * This interface can be used by applications in which blocking is
64 * acceptable while an image is being loaded. It can also be used to
65 * load small images in general. Applications that need progressive
66 * loading can use the #GdkPixbufLoader functionality instead.
67 */
68
69 /**
70 * SECTION:file-saving
71 * @Short_description: Saving a pixbuf to a file.
72 * @Title: File saving
73 *
74 * These functions allow to save a #GdkPixbuf in a number of
75 * file formats. The formatted data can be written to a file
76 * or to a memory buffer. GdkPixBuf can also call a user-defined
77 * callback on the data, which allows to e.g. write the image
78 * to a socket or store it in a database.
79 */
80
81 /**
82 * SECTION:module_interface
83 * @Short_description: Extending GdkPixBuf
84 * @Title: Module Interface
85 *
86 * If GdkPixBuf has been compiled with GModule support, it can be extended by
87 * modules which can load (and perhaps also save) new image and animation
88 * formats. Each loadable module must export a
89 * #GdkPixbufModuleFillInfoFunc function named `fill_info` and
90 * a #GdkPixbufModuleFillVtableFunc function named
91 * `fill_vtable`.
92 *
93 * In order to make format-checking work before actually loading the modules
94 * (which may require dlopening image libraries), modules export their
95 * signatures (and other information) via the `fill_info` function. An
96 * external utility, gdk-pixbuf-query-loaders, uses this to create a text
97 * file containing a list of all available loaders and their signatures.
98 * This file is then read at runtime by GdkPixBuf to obtain the list of
99 * available loaders and their signatures.
100 *
101 * Modules may only implement a subset of the functionality available via
102 * #GdkPixbufModule. If a particular functionality is not implemented, the
103 * `fill_vtable` function will simply not set the corresponding
104 * function pointers of the #GdkPixbufModule structure. If a module supports
105 * incremental loading (i.e. provides #begin_load, #stop_load and
106 * #load_increment), it doesn't have to implement #load, since GdkPixBuf can
107 * supply a generic #load implementation wrapping the incremental loading.
108 *
109 * Installing a module is a two-step process:
110 * - copy the module file(s) to the loader directory (normally
111 * `$libdir/gdk-pixbuf-2.0/$version/loaders`, unless overridden by the
112 * environment variable `GDK_PIXBUF_MODULEDIR`)
113 * - call gdk-pixbuf-query-loaders to update the module file (normally
114 * `$libdir/gdk-pixbuf-2.0/$version/loaders.cache`, unless overridden by the
115 * environment variable `GDK_PIXBUF_MODULE_FILE`)
116 *
117 * The GdkPixBuf interfaces needed for implementing modules are contained in
118 * `gdk-pixbuf-io.h` (and `gdk-pixbuf-animation.h` if the module supports
119 * animations). They are not covered by the same stability guarantees as the
120 * regular GdkPixBuf API. To underline this fact, they are protected by
121 * `#ifdef GDK_PIXBUF_ENABLE_BACKEND`.
122 */
123
124
125 static gint
format_check(GdkPixbufModule * module,guchar * buffer,int size)126 format_check (GdkPixbufModule *module, guchar *buffer, int size)
127 {
128 int i, j;
129 gchar m;
130 GdkPixbufModulePattern *pattern;
131 gboolean anchored;
132 guchar *prefix;
133 gchar *mask;
134
135 for (pattern = module->info->signature; pattern->prefix; pattern++) {
136 if (pattern->mask && pattern->mask[0] == '*') {
137 prefix = (guchar *)pattern->prefix + 1;
138 mask = pattern->mask + 1;
139 anchored = FALSE;
140 }
141 else {
142 prefix = (guchar *)pattern->prefix;
143 mask = pattern->mask;
144 anchored = TRUE;
145 }
146 for (i = 0; i < size; i++) {
147 for (j = 0; i + j < size && prefix[j] != 0; j++) {
148 m = mask ? mask[j] : ' ';
149 if (m == ' ') {
150 if (buffer[i + j] != prefix[j])
151 break;
152 }
153 else if (m == '!') {
154 if (buffer[i + j] == prefix[j])
155 break;
156 }
157 else if (m == 'z') {
158 if (buffer[i + j] != 0)
159 break;
160 }
161 else if (m == 'n') {
162 if (buffer[i + j] == 0)
163 break;
164 }
165 }
166
167 if (prefix[j] == 0)
168 return pattern->relevance;
169
170 if (anchored)
171 break;
172 }
173 }
174 return 0;
175 }
176
177 G_LOCK_DEFINE_STATIC (init_lock);
178
179 static gboolean file_formats_inited;
180 static GSList *file_formats = NULL;
181
182 static gboolean gdk_pixbuf_io_init (void);
183
184 static GSList *
get_file_formats(void)185 get_file_formats (void)
186 {
187 G_LOCK (init_lock);
188 if (file_formats == NULL ||
189 !file_formats_inited)
190 file_formats_inited = gdk_pixbuf_io_init ();
191 G_UNLOCK (init_lock);
192
193 return file_formats;
194 }
195
196 #ifdef G_OS_WIN32
197
198 /* DllMain function needed to tuck away the gdk-pixbuf DLL handle */
199
200 static HMODULE gdk_pixbuf_dll;
201
202 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)203 DllMain (HINSTANCE hinstDLL,
204 DWORD fdwReason,
205 LPVOID lpvReserved)
206 {
207 switch (fdwReason) {
208 case DLL_PROCESS_ATTACH:
209 gdk_pixbuf_dll = (HMODULE) hinstDLL;
210 break;
211 }
212
213 return TRUE;
214 }
215 #endif
216
217
218 #ifdef GDK_PIXBUF_RELOCATABLE
219
220 gchar *
gdk_pixbuf_get_toplevel(void)221 gdk_pixbuf_get_toplevel (void)
222 {
223 static gchar *toplevel = NULL;
224
225 if (toplevel == NULL) {
226 #if defined(G_OS_WIN32)
227 toplevel = g_win32_get_package_installation_directory_of_module (gdk_pixbuf_dll);
228 #elif defined(OS_DARWIN)
229 char pathbuf[PATH_MAX + 1];
230 uint32_t bufsize = sizeof(pathbuf);
231 gchar *bin_dir;
232
233 _NSGetExecutablePath(pathbuf, &bufsize);
234 bin_dir = g_dirname(pathbuf);
235 toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
236 g_free (bin_dir);
237 #elif defined (OS_LINUX)
238 gchar *exe_path, *bin_dir;
239
240 exe_path = g_file_read_link ("/proc/self/exe", NULL);
241 bin_dir = g_dirname(exe_path);
242 toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
243 g_free (exe_path);
244 g_free (bin_dir);
245 #else
246 #error "Relocations not supported for this platform"
247 #endif
248 }
249 return toplevel;
250 }
251
252 #endif /* GDK_PIXBUF_RELOCATABLE */
253
254
255 #ifdef USE_GMODULE
256
257 static gboolean
scan_string(const char ** pos,GString * out)258 scan_string (const char **pos, GString *out)
259 {
260 const char *p = *pos, *q = *pos;
261 char *tmp, *tmp2;
262 gboolean quoted;
263
264 while (g_ascii_isspace (*p))
265 p++;
266
267 if (!*p)
268 return FALSE;
269 else if (*p == '"') {
270 p++;
271 quoted = FALSE;
272 for (q = p; (*q != '"') || quoted; q++) {
273 if (!*q)
274 return FALSE;
275 quoted = (*q == '\\') && !quoted;
276 }
277
278 tmp = g_strndup (p, q - p);
279 tmp2 = g_strcompress (tmp);
280 g_string_truncate (out, 0);
281 g_string_append (out, tmp2);
282 g_free (tmp);
283 g_free (tmp2);
284 }
285
286 q++;
287 *pos = q;
288
289 return TRUE;
290 }
291
292 static gboolean
scan_int(const char ** pos,int * out)293 scan_int (const char **pos, int *out)
294 {
295 int i = 0;
296 char buf[32];
297 const char *p = *pos;
298
299 while (g_ascii_isspace (*p))
300 p++;
301
302 if (*p < '0' || *p > '9')
303 return FALSE;
304
305 while ((*p >= '0') && (*p <= '9') && i < sizeof (buf)) {
306 buf[i] = *p;
307 i++;
308 p++;
309 }
310
311 if (i == sizeof (buf))
312 return FALSE;
313 else
314 buf[i] = '\0';
315
316 *out = atoi (buf);
317
318 *pos = p;
319
320 return TRUE;
321 }
322
323 static gboolean
skip_space(const char ** pos)324 skip_space (const char **pos)
325 {
326 const char *p = *pos;
327
328 while (g_ascii_isspace (*p))
329 p++;
330
331 *pos = p;
332
333 return !(*p == '\0');
334 }
335
336 #ifdef GDK_PIXBUF_RELOCATABLE
337
338 static char *
get_libdir(void)339 get_libdir (void)
340 {
341 static char *libdir = NULL;
342
343 if (libdir == NULL)
344 libdir = g_build_filename (gdk_pixbuf_get_toplevel (), "lib", NULL);
345
346 return libdir;
347 }
348
349 #undef GDK_PIXBUF_LIBDIR
350 #define GDK_PIXBUF_LIBDIR get_libdir()
351
352 #endif /* GDK_PIXBUF_RELOCATABLE */
353
354 /* In case we have a relative module path in the loaders cache
355 * prepend the toplevel dir */
356 static gchar *
build_module_path(const gchar * path)357 build_module_path (const gchar *path)
358 {
359 #ifdef GDK_PIXBUF_RELOCATABLE
360 if (g_path_is_absolute (path)) {
361 return g_strdup (path);
362 } else {
363 return g_build_filename (gdk_pixbuf_get_toplevel (), path, NULL);
364 }
365 #else
366 return g_strdup (path);
367 #endif
368 }
369
370 static gchar *
gdk_pixbuf_get_module_file(void)371 gdk_pixbuf_get_module_file (void)
372 {
373 gchar *result = g_strdup (g_getenv ("GDK_PIXBUF_MODULE_FILE"));
374
375 if (!result)
376 result = g_build_filename (GDK_PIXBUF_LIBDIR, "gdk-pixbuf-2.0", GDK_PIXBUF_BINARY_VERSION, "loaders.cache", NULL);
377
378 return result;
379 }
380
381 #endif /* USE_GMODULE */
382
383
384 static gboolean
385 gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
386 GError **error);
387
388 static gboolean
gdk_pixbuf_io_init_modules(const char * filename,GError ** error)389 gdk_pixbuf_io_init_modules (const char *filename,
390 GError **error)
391 {
392 #ifdef USE_GMODULE
393 GIOChannel *channel;
394 gchar *line_buf;
395 gsize term;
396 GString *tmp_buf = g_string_new (NULL);
397 gboolean have_error = FALSE;
398 GdkPixbufModule *module = NULL;
399 int flags;
400 int n_patterns = 0;
401 GdkPixbufModulePattern *pattern;
402 GError *local_error = NULL;
403 guint num_formats;
404
405 channel = g_io_channel_new_file (filename, "r", &local_error);
406 if (!channel) {
407 g_set_error (error,
408 G_IO_ERROR,
409 G_IO_ERROR_INVALID_ARGUMENT,
410 "Cannot open pixbuf loader module file '%s': %s\n\n"
411 "This likely means that your installation is broken.\n"
412 "Try running the command\n"
413 " gdk-pixbuf-query-loaders > %s\n"
414 "to make things work again for the time being.",
415 filename, local_error->message, filename);
416 g_clear_error (&local_error);
417 g_string_free (tmp_buf, TRUE);
418 return FALSE;
419 }
420
421 num_formats = g_slist_length (file_formats);
422
423 while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL, &term, NULL) == G_IO_STATUS_NORMAL) {
424 const char *p;
425
426 p = line_buf;
427
428 line_buf[term] = 0;
429
430 if (!skip_space (&p)) {
431 /* Blank line marking the end of a module
432 */
433 if (module && *p != '#') {
434 file_formats = g_slist_prepend (file_formats, module);
435 module = NULL;
436 }
437
438 goto next_line;
439 }
440
441 if (*p == '#')
442 goto next_line;
443
444 if (!module) {
445 /* Read a module location
446 */
447 module = g_new0 (GdkPixbufModule, 1);
448 n_patterns = 0;
449
450 if (!scan_string (&p, tmp_buf)) {
451 g_warning ("Error parsing loader info in '%s'\n %s",
452 filename, line_buf);
453 have_error = TRUE;
454 }
455 module->module_path = build_module_path (tmp_buf->str);
456 }
457 else if (!module->module_name) {
458 module->info = g_new0 (GdkPixbufFormat, 1);
459 if (!scan_string (&p, tmp_buf)) {
460 g_warning ("Error parsing loader info in '%s'\n %s",
461 filename, line_buf);
462 have_error = TRUE;
463 }
464 module->info->name = g_strdup (tmp_buf->str);
465 module->module_name = module->info->name;
466
467 if (!scan_int (&p, &flags)) {
468 g_warning ("Error parsing loader info in '%s'\n %s",
469 filename, line_buf);
470 have_error = TRUE;
471 }
472 module->info->flags = flags;
473
474 if (!scan_string (&p, tmp_buf)) {
475 g_warning ("Error parsing loader info in '%s'\n %s",
476 filename, line_buf);
477 have_error = TRUE;
478 }
479 if (tmp_buf->str[0] != 0)
480 module->info->domain = g_strdup (tmp_buf->str);
481
482 if (!scan_string (&p, tmp_buf)) {
483 g_warning ("Error parsing loader info in '%s'\n %s",
484 filename, line_buf);
485 have_error = TRUE;
486 }
487 module->info->description = g_strdup (tmp_buf->str);
488
489 if (scan_string (&p, tmp_buf)) {
490 module->info->license = g_strdup (tmp_buf->str);
491 }
492 }
493 else if (!module->info->mime_types) {
494 int n = 1;
495 module->info->mime_types = g_new0 (gchar*, 1);
496 while (scan_string (&p, tmp_buf)) {
497 if (tmp_buf->str[0] != 0) {
498 module->info->mime_types =
499 g_realloc (module->info->mime_types, (n + 1) * sizeof (gchar*));
500 module->info->mime_types[n - 1] = g_strdup (tmp_buf->str);
501 module->info->mime_types[n] = NULL;
502 n++;
503 }
504 }
505 }
506 else if (!module->info->extensions) {
507 int n = 1;
508 module->info->extensions = g_new0 (gchar*, 1);
509 while (scan_string (&p, tmp_buf)) {
510 if (tmp_buf->str[0] != 0) {
511 module->info->extensions =
512 g_realloc (module->info->extensions, (n + 1) * sizeof (gchar*));
513 module->info->extensions[n - 1] = g_strdup (tmp_buf->str);
514 module->info->extensions[n] = NULL;
515 n++;
516 }
517 }
518 }
519 else {
520 n_patterns++;
521 module->info->signature = (GdkPixbufModulePattern *)
522 g_realloc (module->info->signature, (n_patterns + 1) * sizeof (GdkPixbufModulePattern));
523 pattern = module->info->signature + n_patterns;
524 pattern->prefix = NULL;
525 pattern->mask = NULL;
526 pattern->relevance = 0;
527 pattern--;
528 if (!scan_string (&p, tmp_buf))
529 goto context_error;
530 pattern->prefix = g_strdup (tmp_buf->str);
531
532 if (!scan_string (&p, tmp_buf))
533 goto context_error;
534 if (*tmp_buf->str)
535 pattern->mask = g_strdup (tmp_buf->str);
536 else
537 pattern->mask = NULL;
538
539 if (!scan_int (&p, &pattern->relevance))
540 goto context_error;
541
542 goto next_line;
543
544 context_error:
545 g_free (pattern->prefix);
546 g_free (pattern->mask);
547 g_free (pattern);
548 g_warning ("Error parsing loader info in '%s'\n %s",
549 filename, line_buf);
550 have_error = TRUE;
551 }
552 next_line:
553 g_free (line_buf);
554 }
555 g_string_free (tmp_buf, TRUE);
556 g_io_channel_unref (channel);
557
558 if (g_slist_length (file_formats) <= num_formats) {
559 g_set_error (error,
560 G_IO_ERROR,
561 G_IO_ERROR_NOT_INITIALIZED,
562 "No new GdkPixbufModule loaded from '%s'",
563 filename);
564 return FALSE;
565 }
566 #endif
567 return TRUE;
568 }
569
570 /**
571 * gdk_pixbuf_init_modules:
572 * @path: Path to directory where the loaders.cache is installed
573 * @error: return location for a #GError
574 *
575 * Initalizes the gdk-pixbuf loader modules referenced by the loaders.cache
576 * file present inside that directory.
577 *
578 * This is to be used by applications that want to ship certain loaders
579 * in a different location from the system ones.
580 *
581 * This is needed when the OS or runtime ships a minimal number of loaders
582 * so as to reduce the potential attack surface of carefully crafted image
583 * files, especially for uncommon file types. Applications that require
584 * broader image file types coverage, such as image viewers, would be
585 * expected to ship the gdk-pixbuf modules in a separate location, bundled
586 * with the application in a separate directory from the OS or runtime-
587 * provided modules.
588 *
589 * Since: 2.40
590 */
591 gboolean
gdk_pixbuf_init_modules(const char * path,GError ** error)592 gdk_pixbuf_init_modules (const char *path,
593 GError **error)
594 {
595 char *filename;
596 gboolean ret;
597
598 g_return_val_if_fail (path != NULL, FALSE);
599 filename = g_build_filename (path, "loaders.cache", NULL);
600 ret = gdk_pixbuf_io_init_modules (filename, error);
601 g_free (filename);
602 return ret;
603 }
604
605 static void
gdk_pixbuf_io_init_builtin(void)606 gdk_pixbuf_io_init_builtin (void)
607 {
608 #define load_one_builtin_module(format) G_STMT_START { \
609 GdkPixbufModule *__builtin_module = g_new0 (GdkPixbufModule, 1); \
610 __builtin_module->module_name = #format; \
611 if (gdk_pixbuf_load_module_unlocked (__builtin_module, NULL)) \
612 file_formats = g_slist_prepend (file_formats, __builtin_module); \
613 else \
614 g_free (__builtin_module); } G_STMT_END
615
616 #ifdef INCLUDE_ani
617 load_one_builtin_module (ani);
618 #endif
619 #ifdef INCLUDE_png
620 load_one_builtin_module (png);
621 #endif
622 #ifdef INCLUDE_bmp
623 load_one_builtin_module (bmp);
624 #endif
625 #ifdef INCLUDE_gif
626 load_one_builtin_module (gif);
627 #endif
628 #ifdef INCLUDE_ico
629 load_one_builtin_module (ico);
630 #endif
631 #ifdef INCLUDE_jpeg
632 load_one_builtin_module (jpeg);
633 #endif
634 #ifdef INCLUDE_pnm
635 load_one_builtin_module (pnm);
636 #endif
637 #ifdef INCLUDE_tiff
638 load_one_builtin_module (tiff);
639 #endif
640 #ifdef INCLUDE_xpm
641 load_one_builtin_module (xpm);
642 #endif
643 #ifdef INCLUDE_xbm
644 load_one_builtin_module (xbm);
645 #endif
646 #ifdef INCLUDE_tga
647 load_one_builtin_module (tga);
648 #endif
649 #ifdef INCLUDE_icns
650 load_one_builtin_module (icns);
651 #endif
652 #ifdef INCLUDE_jasper
653 load_one_builtin_module (jasper);
654 #endif
655 #ifdef INCLUDE_qtif
656 load_one_builtin_module (qtif);
657 #endif
658 #ifdef INCLUDE_gdiplus
659 /* We don't bother having the GDI+ loaders individually selectable
660 * for building in or not.
661 */
662 load_one_builtin_module (ico);
663 load_one_builtin_module (wmf);
664 load_one_builtin_module (emf);
665 load_one_builtin_module (bmp);
666 load_one_builtin_module (gif);
667 load_one_builtin_module (jpeg);
668 load_one_builtin_module (tiff);
669 #endif
670 #ifdef INCLUDE_gdip_png
671 /* Except the gdip-png loader which normally isn't built at all even */
672 load_one_builtin_module (png);
673 #endif
674
675 #undef load_one_builtin_module
676 }
677
678 static gboolean
gdk_pixbuf_io_init(void)679 gdk_pixbuf_io_init (void)
680 {
681 char *module_file;
682 gboolean ret;
683
684 gdk_pixbuf_io_init_builtin ();
685 module_file = gdk_pixbuf_get_module_file ();
686 ret = gdk_pixbuf_io_init_modules (module_file, NULL);
687 g_free (module_file);
688 return ret;
689 }
690
691 #define module(type) \
692 extern void _gdk_pixbuf__##type##_fill_info (GdkPixbufFormat *info); \
693 extern void _gdk_pixbuf__##type##_fill_vtable (GdkPixbufModule *module)
694
695 module (png);
696 module (jpeg);
697 module (gif);
698 module (ico);
699 module (ani);
700 module (xpm);
701 module (tiff);
702 module (pnm);
703 module (bmp);
704 module (xbm);
705 module (tga);
706 module (icns);
707 module (jasper);
708 module (qtif);
709 module (gdip_ico);
710 module (gdip_wmf);
711 module (gdip_emf);
712 module (gdip_bmp);
713 module (gdip_gif);
714 module (gdip_jpeg);
715 module (gdip_png);
716 module (gdip_tiff);
717
718 #undef module
719
720 /* actually load the image handler - gdk_pixbuf_get_module only get a */
721 /* reference to the module to load, it doesn't actually load it */
722 /* perhaps these actions should be combined in one function */
723 static gboolean
gdk_pixbuf_load_module_unlocked(GdkPixbufModule * image_module,GError ** error)724 gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
725 GError **error)
726 {
727 GdkPixbufModuleFillInfoFunc fill_info = NULL;
728 GdkPixbufModuleFillVtableFunc fill_vtable = NULL;
729
730 if (image_module->module != NULL)
731 return TRUE;
732
733 #define try_module(format,id) \
734 if (fill_info == NULL && \
735 strcmp (image_module->module_name, #format) == 0) { \
736 fill_info = _gdk_pixbuf__##id##_fill_info; \
737 fill_vtable = _gdk_pixbuf__##id##_fill_vtable; \
738 }
739
740 #ifdef INCLUDE_gdiplus
741 try_module (ico,gdip_ico);
742 try_module (wmf,gdip_wmf);
743 try_module (emf,gdip_emf);
744 try_module (bmp,gdip_bmp);
745 try_module (gif,gdip_gif);
746 try_module (jpeg,gdip_jpeg);
747 try_module (tiff,gdip_tiff);
748 #endif
749 #ifdef INCLUDE_gdip_png
750 try_module (png,gdip_png);
751 #endif
752 #ifdef INCLUDE_png
753 try_module (png,png);
754 #endif
755 #ifdef INCLUDE_bmp
756 try_module (bmp,bmp);
757 #endif
758 #ifdef INCLUDE_gif
759 try_module (gif,gif);
760 #endif
761 #ifdef INCLUDE_ico
762 try_module (ico,ico);
763 #endif
764 #ifdef INCLUDE_ani
765 try_module (ani,ani);
766 #endif
767 #ifdef INCLUDE_jpeg
768 try_module (jpeg,jpeg);
769 #endif
770 #ifdef INCLUDE_pnm
771 try_module (pnm,pnm);
772 #endif
773 #ifdef INCLUDE_tiff
774 try_module (tiff,tiff);
775 #endif
776 #ifdef INCLUDE_xpm
777 try_module (xpm,xpm);
778 #endif
779 #ifdef INCLUDE_xbm
780 try_module (xbm,xbm);
781 #endif
782 #ifdef INCLUDE_tga
783 try_module (tga,tga);
784 #endif
785 #ifdef INCLUDE_icns
786 try_module (icns,icns);
787 #endif
788 #ifdef INCLUDE_jasper
789 try_module (jasper,jasper);
790 #endif
791 #ifdef INCLUDE_qtif
792 try_module (qtif,qtif);
793 #endif
794
795 #undef try_module
796
797 if (fill_vtable) {
798 image_module->module = (void *) 1;
799 (* fill_vtable) (image_module);
800 if (image_module->info == NULL) {
801 image_module->info = g_new0 (GdkPixbufFormat, 1);
802 (* fill_info) (image_module->info);
803 }
804 return TRUE;
805 }
806 else
807 #ifdef USE_GMODULE
808 {
809 char *path;
810 GModule *module;
811 gpointer sym;
812
813 path = image_module->module_path;
814 module = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
815
816 if (!module) {
817 g_set_error (error,
818 GDK_PIXBUF_ERROR,
819 GDK_PIXBUF_ERROR_FAILED,
820 _("Unable to load image-loading module: %s: %s"),
821 path, g_module_error ());
822 return FALSE;
823 }
824
825 image_module->module = module;
826
827 if (g_module_symbol (module, "fill_vtable", &sym)) {
828 fill_vtable = (GdkPixbufModuleFillVtableFunc) sym;
829 (* fill_vtable) (image_module);
830 return TRUE;
831 } else {
832 g_set_error (error,
833 GDK_PIXBUF_ERROR,
834 GDK_PIXBUF_ERROR_FAILED,
835 _("Image-loading module %s does not export the proper interface; perhaps it’s from a different gdk-pixbuf version?"),
836 path);
837 return FALSE;
838 }
839 }
840 #else
841 g_set_error (error,
842 GDK_PIXBUF_ERROR,
843 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
844 _("Image type “%s” is not supported"),
845 image_module->module_name);
846 return FALSE;
847 #endif /* !USE_GMODULE */
848 }
849
850
851 gboolean
_gdk_pixbuf_load_module(GdkPixbufModule * image_module,GError ** error)852 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
853 GError **error)
854 {
855 gboolean ret;
856
857 G_LOCK (init_lock);
858
859 ret = gdk_pixbuf_load_module_unlocked (image_module, error);
860
861 G_UNLOCK (init_lock);
862
863 return ret;
864 }
865
866
867
868 GdkPixbufModule *
_gdk_pixbuf_get_named_module(const char * name,GError ** error)869 _gdk_pixbuf_get_named_module (const char *name,
870 GError **error)
871 {
872 GSList *modules;
873
874 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
875 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
876
877 if (module->info->disabled)
878 continue;
879
880 if (!strcmp (name, module->module_name))
881 return module;
882 }
883
884 g_set_error (error,
885 GDK_PIXBUF_ERROR,
886 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
887 _("Image type “%s” is not supported"),
888 name);
889
890 return NULL;
891 }
892
893 GdkPixbufModule *
_gdk_pixbuf_get_module(guchar * buffer,guint size,const gchar * filename,GError ** error)894 _gdk_pixbuf_get_module (guchar *buffer, guint size,
895 const gchar *filename,
896 GError **error)
897 {
898 GSList *modules;
899
900 GdkPixbufModule *selected = NULL;
901 gchar *display_name = NULL;
902 #ifdef GDK_PIXBUF_USE_GIO_MIME
903 gchar *mime_type;
904 gchar **mimes;
905 gchar *type;
906 gint j;
907 gboolean uncertain;
908
909 mime_type = g_content_type_guess (NULL, buffer, size, &uncertain);
910 if ((uncertain || g_str_equal (mime_type, "text/plain") || g_str_equal (mime_type, "application/gzip")) && filename != NULL) {
911 g_free (mime_type);
912 mime_type = g_content_type_guess (filename, buffer, size, NULL);
913 }
914
915 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
916 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
917 GdkPixbufFormat *info = module->info;
918
919 if (info->disabled)
920 continue;
921
922 mimes = info->mime_types;
923 for (j = 0; mimes[j] != NULL; j++) {
924 type = g_content_type_from_mime_type (mimes[j]);
925 if (g_content_type_equals (type, mime_type)) {
926 g_free (type);
927 selected = module;
928 break;
929 }
930 g_free (type);
931 }
932
933 if (selected != NULL)
934 break;
935
936 /* Make sure the builtin GdkPixdata support works even without mime sniffing */
937 if (strcmp (info->name, "GdkPixdata") == 0 &&
938 format_check (module, buffer, size) == 100) {
939 selected = module;
940 break;
941 }
942 }
943 g_free (mime_type);
944 #else
945 gint score, best = 0;
946
947 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
948 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
949
950 if (module->info->disabled)
951 continue;
952
953 score = format_check (module, buffer, size);
954 if (score > best) {
955 best = score;
956 selected = module;
957 }
958 if (score >= 100)
959 break;
960 }
961 #endif
962
963 if (selected != NULL)
964 return selected;
965
966 if (filename)
967 {
968 display_name = g_filename_display_name (filename);
969 g_set_error (error,
970 GDK_PIXBUF_ERROR,
971 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
972 _("Couldn’t recognize the image file format for file “%s”"),
973 display_name);
974 g_free (display_name);
975 }
976 else
977 g_set_error_literal (error,
978 GDK_PIXBUF_ERROR,
979 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
980 _("Unrecognized image file format"));
981
982
983 return NULL;
984 }
985
986 static
987 GdkPixbufModule *
_gdk_pixbuf_get_module_for_file(FILE * f,const gchar * filename,GError ** error)988 _gdk_pixbuf_get_module_for_file (FILE *f, const gchar *filename, GError **error)
989 {
990 guchar buffer[SNIFF_BUFFER_SIZE];
991 int size;
992
993 size = fread (&buffer, 1, sizeof (buffer), f);
994 if (size == 0) {
995 gchar *display_name;
996 display_name = g_filename_display_name (filename);
997 g_set_error (error,
998 GDK_PIXBUF_ERROR,
999 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
1000 _("Image file “%s” contains no data"),
1001 display_name);
1002 g_free (display_name);
1003 return NULL;
1004 }
1005
1006 return _gdk_pixbuf_get_module (buffer, size, filename, error);
1007 }
1008
1009 static void
prepared_notify(GdkPixbuf * pixbuf,GdkPixbufAnimation * anim,gpointer user_data)1010 prepared_notify (GdkPixbuf *pixbuf,
1011 GdkPixbufAnimation *anim,
1012 gpointer user_data)
1013 {
1014 if (pixbuf != NULL)
1015 g_object_ref (pixbuf);
1016 *((GdkPixbuf **)user_data) = pixbuf;
1017 }
1018
1019 static GdkPixbuf *
generic_load_incrementally(GdkPixbufModule * module,FILE * f,GError ** error)1020 generic_load_incrementally (GdkPixbufModule *module, FILE *f, GError **error)
1021 {
1022 GdkPixbuf *pixbuf = NULL;
1023 gpointer context;
1024
1025 context = module->begin_load (NULL, prepared_notify, NULL, &pixbuf, error);
1026
1027 if (!context)
1028 goto out;
1029
1030 while (!feof (f) && !ferror (f)) {
1031 guchar buffer[LOAD_BUFFER_SIZE];
1032 size_t length;
1033
1034 length = fread (buffer, 1, sizeof (buffer), f);
1035 if (length > 0) {
1036 if (!module->load_increment (context, buffer, length, error)) {
1037 module->stop_load (context, NULL);
1038 if (pixbuf != NULL) {
1039 g_object_unref (pixbuf);
1040 pixbuf = NULL;
1041 }
1042 goto out;
1043 }
1044 }
1045 }
1046
1047 if (!module->stop_load (context, error)) {
1048 if (pixbuf != NULL) {
1049 g_object_unref (pixbuf);
1050 pixbuf = NULL;
1051 }
1052 }
1053
1054 out:
1055 return pixbuf;
1056 }
1057
1058 GdkPixbuf *
_gdk_pixbuf_generic_image_load(GdkPixbufModule * module,FILE * f,GError ** error)1059 _gdk_pixbuf_generic_image_load (GdkPixbufModule *module, FILE *f, GError **error)
1060 {
1061 GdkPixbuf *pixbuf = NULL;
1062
1063 if (module->load != NULL) {
1064 pixbuf = (* module->load) (f, error);
1065 } else if (module->begin_load != NULL) {
1066 pixbuf = generic_load_incrementally (module, f, error);
1067 } else if (module->load_animation != NULL) {
1068 GdkPixbufAnimation *animation;
1069
1070 animation = (* module->load_animation) (f, error);
1071 if (animation != NULL) {
1072 pixbuf = gdk_pixbuf_animation_get_static_image (animation);
1073
1074 g_object_ref (pixbuf);
1075 g_object_unref (animation);
1076 }
1077 }
1078
1079 return pixbuf;
1080 }
1081
1082 /**
1083 * gdk_pixbuf_new_from_file:
1084 * @filename: (type filename): Name of file to load, in the GLib file
1085 * name encoding
1086 * @error: Return location for an error
1087 *
1088 * Creates a new pixbuf by loading an image from a file. The file format is
1089 * detected automatically. If %NULL is returned, then @error will be set.
1090 * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
1091 *
1092 * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if
1093 * any of several error conditions occurred: the file could not be opened,
1094 * there was no loader for the file's format, there was not enough memory to
1095 * allocate the image buffer, or the image file contained invalid data.
1096 **/
1097 GdkPixbuf *
gdk_pixbuf_new_from_file(const char * filename,GError ** error)1098 gdk_pixbuf_new_from_file (const char *filename,
1099 GError **error)
1100 {
1101 GdkPixbuf *pixbuf;
1102 FILE *f;
1103 GdkPixbufModule *image_module;
1104
1105 g_return_val_if_fail (filename != NULL, NULL);
1106 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1107
1108 f = g_fopen (filename, "rb");
1109 if (!f) {
1110 gint save_errno = errno;
1111 gchar *display_name;
1112 display_name = g_filename_display_name (filename);
1113 g_set_error (error,
1114 G_FILE_ERROR,
1115 g_file_error_from_errno (save_errno),
1116 _("Failed to open file “%s”: %s"),
1117 display_name,
1118 g_strerror (save_errno));
1119 g_free (display_name);
1120 return NULL;
1121 }
1122
1123 image_module = _gdk_pixbuf_get_module_for_file (f, filename, error);
1124 if (image_module == NULL) {
1125 fclose (f);
1126 return NULL;
1127 }
1128
1129 if (!_gdk_pixbuf_load_module (image_module, error)) {
1130 fclose (f);
1131 return NULL;
1132 }
1133
1134 fseek (f, 0, SEEK_SET);
1135 pixbuf = _gdk_pixbuf_generic_image_load (image_module, f, error);
1136 fclose (f);
1137
1138 if (pixbuf == NULL && error != NULL && *error == NULL) {
1139
1140 /* I don't trust these crufty longjmp()'ing image libs
1141 * to maintain proper error invariants, and I don't
1142 * want user code to segfault as a result. We need to maintain
1143 * the invariant that error gets set if NULL is returned.
1144 */
1145
1146 gchar *display_name;
1147 display_name = g_filename_display_name (filename);
1148 g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
1149 g_set_error (error,
1150 GDK_PIXBUF_ERROR,
1151 GDK_PIXBUF_ERROR_FAILED,
1152 _("Failed to load image “%s”: reason not known, probably a corrupt image file"),
1153 display_name);
1154 g_free (display_name);
1155 } else if (error != NULL && *error != NULL) {
1156 /* Add the filename to the error message */
1157 GError *e = *error;
1158 gchar *old;
1159 gchar *display_name;
1160
1161 display_name = g_filename_display_name (filename);
1162 old = e->message;
1163 e->message = g_strdup_printf (_("Failed to load image “%s”: %s"),
1164 display_name,
1165 old);
1166 g_free (old);
1167 g_free (display_name);
1168 }
1169
1170 return pixbuf;
1171 }
1172
1173 #ifdef G_OS_WIN32
1174
1175 /**
1176 * gdk_pixbuf_new_from_file_utf8:
1177 * @filename: (type filename): Name of file to load, in the GLib file name encoding
1178 * @error: Return location for an error
1179 *
1180 * Same as gdk_pixbuf_new_from_file()
1181 *
1182 * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if
1183 * any of several error conditions occurred: the file could not be opened,
1184 * there was no loader for the file's format, there was not enough memory to
1185 * allocate the image buffer, or the image file contained invalid data.
1186 **/
1187 GdkPixbuf *
gdk_pixbuf_new_from_file_utf8(const char * filename,GError ** error)1188 gdk_pixbuf_new_from_file_utf8 (const char *filename,
1189 GError **error)
1190 {
1191 return gdk_pixbuf_new_from_file (filename, error);
1192 }
1193
1194 #endif
1195
1196
1197 /**
1198 * gdk_pixbuf_new_from_file_at_size:
1199 * @filename: (type filename): Name of file to load, in the GLib file
1200 * name encoding
1201 * @width: The width the image should have or -1 to not constrain the width
1202 * @height: The height the image should have or -1 to not constrain the height
1203 * @error: Return location for an error
1204 *
1205 * Creates a new pixbuf by loading an image from a file.
1206 * The file format is detected automatically. If %NULL is returned, then
1207 * @error will be set. Possible errors are in the #GDK_PIXBUF_ERROR and
1208 * #G_FILE_ERROR domains.
1209 *
1210 * The image will be scaled to fit in the requested size, preserving
1211 * the image's aspect ratio. Note that the returned pixbuf may be smaller
1212 * than @width x @height, if the aspect ratio requires it. To load
1213 * and image at the requested size, regardless of aspect ratio, use
1214 * gdk_pixbuf_new_from_file_at_scale().
1215 *
1216 * Return value: A newly-created pixbuf with a reference count of 1, or
1217 * %NULL if any of several error conditions occurred: the file could not
1218 * be opened, there was no loader for the file's format, there was not
1219 * enough memory to allocate the image buffer, or the image file contained
1220 * invalid data.
1221 *
1222 * Since: 2.4
1223 **/
1224 GdkPixbuf *
gdk_pixbuf_new_from_file_at_size(const char * filename,int width,int height,GError ** error)1225 gdk_pixbuf_new_from_file_at_size (const char *filename,
1226 int width,
1227 int height,
1228 GError **error)
1229 {
1230 return gdk_pixbuf_new_from_file_at_scale (filename,
1231 width, height,
1232 TRUE, error);
1233 }
1234
1235 #ifdef G_OS_WIN32
1236
1237 /**
1238 * gdk_pixbuf_new_from_file_at_size_utf8:
1239 * @filename: (type filename): Name of file to load, in the GLib file name encoding
1240 * @width: The width the image should have or -1 to not constrain the width
1241 * @height: The height the image should have or -1 to not constrain the height
1242 * @error: Return location for an error
1243 *
1244 * Same as gdk_pixbuf_new_from_file_at_size()
1245 *
1246 * Return value: A newly-created pixbuf with a reference count of 1, or
1247 * %NULL if any of several error conditions occurred: the file could not
1248 * be opened, there was no loader for the file's format, there was not
1249 * enough memory to allocate the image buffer, or the image file contained
1250 * invalid data.
1251 *
1252 * Since: 2.4
1253 **/
1254 GdkPixbuf *
gdk_pixbuf_new_from_file_at_size_utf8(const char * filename,int width,int height,GError ** error)1255 gdk_pixbuf_new_from_file_at_size_utf8 (const char *filename,
1256 int width,
1257 int height,
1258 GError **error)
1259 {
1260 return gdk_pixbuf_new_from_file_at_size (filename, width, height, error);
1261 }
1262
1263 #endif
1264
1265 typedef struct {
1266 gint width;
1267 gint height;
1268 gboolean preserve_aspect_ratio;
1269 } AtScaleData;
1270
1271 static void
at_scale_data_async_data_free(AtScaleData * data)1272 at_scale_data_async_data_free (AtScaleData *data)
1273 {
1274 g_slice_free (AtScaleData, data);
1275 }
1276
1277 static void
at_scale_size_prepared_cb(GdkPixbufLoader * loader,int width,int height,gpointer data)1278 at_scale_size_prepared_cb (GdkPixbufLoader *loader,
1279 int width,
1280 int height,
1281 gpointer data)
1282 {
1283 AtScaleData *info = data;
1284
1285 g_return_if_fail (width > 0 && height > 0);
1286
1287 if (info->preserve_aspect_ratio &&
1288 (info->width > 0 || info->height > 0)) {
1289 if (info->width < 0)
1290 {
1291 width = width * (double)info->height/(double)height;
1292 height = info->height;
1293 }
1294 else if (info->height < 0)
1295 {
1296 height = height * (double)info->width/(double)width;
1297 width = info->width;
1298 }
1299 else if ((double)height * (double)info->width >
1300 (double)width * (double)info->height) {
1301 width = 0.5 + (double)width * (double)info->height / (double)height;
1302 height = info->height;
1303 } else {
1304 height = 0.5 + (double)height * (double)info->width / (double)width;
1305 width = info->width;
1306 }
1307 } else {
1308 if (info->width > 0)
1309 width = info->width;
1310 if (info->height > 0)
1311 height = info->height;
1312 }
1313
1314 width = MAX (width, 1);
1315 height = MAX (height, 1);
1316
1317 gdk_pixbuf_loader_set_size (loader, width, height);
1318 }
1319
1320 /**
1321 * gdk_pixbuf_new_from_file_at_scale:
1322 * @filename: (type filename): Name of file to load, in the GLib file
1323 * name encoding
1324 * @width: The width the image should have or -1 to not constrain the width
1325 * @height: The height the image should have or -1 to not constrain the height
1326 * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1327 * @error: Return location for an error
1328 *
1329 * Creates a new pixbuf by loading an image from a file. The file format is
1330 * detected automatically. If %NULL is returned, then @error will be set.
1331 * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
1332 * The image will be scaled to fit in the requested size, optionally preserving
1333 * the image's aspect ratio.
1334 *
1335 * When preserving the aspect ratio, a @width of -1 will cause the image
1336 * to be scaled to the exact given height, and a @height of -1 will cause
1337 * the image to be scaled to the exact given width. When not preserving
1338 * aspect ratio, a @width or @height of -1 means to not scale the image
1339 * at all in that dimension. Negative values for @width and @height are
1340 * allowed since 2.8.
1341 *
1342 * Return value: A newly-created pixbuf with a reference count of 1, or %NULL
1343 * if any of several error conditions occurred: the file could not be opened,
1344 * there was no loader for the file's format, there was not enough memory to
1345 * allocate the image buffer, or the image file contained invalid data.
1346 *
1347 * Since: 2.6
1348 **/
1349 GdkPixbuf *
gdk_pixbuf_new_from_file_at_scale(const char * filename,int width,int height,gboolean preserve_aspect_ratio,GError ** error)1350 gdk_pixbuf_new_from_file_at_scale (const char *filename,
1351 int width,
1352 int height,
1353 gboolean preserve_aspect_ratio,
1354 GError **error)
1355 {
1356
1357 GdkPixbufLoader *loader;
1358 GdkPixbuf *pixbuf;
1359 guchar buffer[LOAD_BUFFER_SIZE];
1360 int length;
1361 FILE *f;
1362 AtScaleData info;
1363 GdkPixbufAnimation *animation;
1364 GdkPixbufAnimationIter *iter;
1365 gboolean has_frame;
1366
1367 g_return_val_if_fail (filename != NULL, NULL);
1368 g_return_val_if_fail (width > 0 || width == -1, NULL);
1369 g_return_val_if_fail (height > 0 || height == -1, NULL);
1370
1371 f = g_fopen (filename, "rb");
1372 if (!f) {
1373 gint save_errno = errno;
1374 gchar *display_name = g_filename_display_name (filename);
1375 g_set_error (error,
1376 G_FILE_ERROR,
1377 g_file_error_from_errno (save_errno),
1378 _("Failed to open file “%s”: %s"),
1379 display_name,
1380 g_strerror (save_errno));
1381 g_free (display_name);
1382 return NULL;
1383 }
1384
1385 loader = _gdk_pixbuf_loader_new_with_filename (filename);
1386
1387 info.width = width;
1388 info.height = height;
1389 info.preserve_aspect_ratio = preserve_aspect_ratio;
1390
1391 g_signal_connect (loader, "size-prepared",
1392 G_CALLBACK (at_scale_size_prepared_cb), &info);
1393
1394 has_frame = FALSE;
1395 while (!has_frame && !feof (f) && !ferror (f)) {
1396 length = fread (buffer, 1, sizeof (buffer), f);
1397 if (length > 0)
1398 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
1399 gdk_pixbuf_loader_close (loader, NULL);
1400 fclose (f);
1401 g_object_unref (loader);
1402 return NULL;
1403 }
1404
1405 animation = gdk_pixbuf_loader_get_animation (loader);
1406 if (animation) {
1407 iter = gdk_pixbuf_animation_get_iter (animation, NULL);
1408 if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) {
1409 has_frame = TRUE;
1410 }
1411 g_object_unref (iter);
1412 }
1413 }
1414
1415 fclose (f);
1416
1417 if (!gdk_pixbuf_loader_close (loader, error) && !has_frame) {
1418 g_object_unref (loader);
1419 return NULL;
1420 }
1421
1422 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1423
1424 if (!pixbuf) {
1425 gchar *display_name = g_filename_display_name (filename);
1426 g_object_unref (loader);
1427 g_set_error (error,
1428 GDK_PIXBUF_ERROR,
1429 GDK_PIXBUF_ERROR_FAILED,
1430 _("Failed to load image “%s”: reason not known, probably a corrupt image file"),
1431 display_name);
1432 g_free (display_name);
1433 return NULL;
1434 }
1435
1436 g_object_ref (pixbuf);
1437
1438 g_object_unref (loader);
1439
1440 return pixbuf;
1441 }
1442
1443 #ifdef G_OS_WIN32
1444
1445 /**
1446 * gdk_pixbuf_new_from_file_at_scale_utf8:
1447 * @filename: (type filename): Name of file to load, in the GLib file name encoding
1448 * @width: The width the image should have or -1 to not constrain the width
1449 * @height: The height the image should have or -1 to not constrain the height
1450 * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1451 * @error: Return location for an error
1452 *
1453 * Same as gdk_pixbuf_new_from_file_at_scale().
1454 *
1455 * Return value: A newly-created pixbuf with a reference count of 1, or %NULL
1456 * if any of several error conditions occurred: the file could not be opened,
1457 * there was no loader for the file's format, there was not enough memory to
1458 * allocate the image buffer, or the image file contained invalid data.
1459 *
1460 * Since: 2.6
1461 **/
1462 GdkPixbuf *
gdk_pixbuf_new_from_file_at_scale_utf8(const char * filename,int width,int height,gboolean preserve_aspect_ratio,GError ** error)1463 gdk_pixbuf_new_from_file_at_scale_utf8 (const char *filename,
1464 int width,
1465 int height,
1466 gboolean preserve_aspect_ratio,
1467 GError **error)
1468 {
1469 return gdk_pixbuf_new_from_file_at_scale (filename, width, height,
1470 preserve_aspect_ratio, error);
1471 }
1472 #endif
1473
1474
1475 static GdkPixbuf *
load_from_stream(GdkPixbufLoader * loader,GInputStream * stream,GCancellable * cancellable,GError ** error)1476 load_from_stream (GdkPixbufLoader *loader,
1477 GInputStream *stream,
1478 GCancellable *cancellable,
1479 GError **error)
1480 {
1481 GdkPixbuf *pixbuf;
1482 gssize n_read;
1483 guchar buffer[LOAD_BUFFER_SIZE];
1484
1485 while (1) {
1486 n_read = g_input_stream_read (stream,
1487 buffer,
1488 sizeof (buffer),
1489 cancellable,
1490 error);
1491 if (n_read < 0) {
1492 gdk_pixbuf_loader_close (loader, NULL);
1493 return NULL;
1494 }
1495
1496 if (n_read == 0)
1497 break;
1498
1499 if (!gdk_pixbuf_loader_write (loader,
1500 buffer,
1501 n_read,
1502 error)) {
1503 gdk_pixbuf_loader_close (loader, NULL);
1504 return NULL;
1505 }
1506 }
1507
1508 if (!gdk_pixbuf_loader_close (loader, error))
1509 return NULL;
1510
1511 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1512 if (pixbuf == NULL)
1513 return NULL;
1514
1515 return g_object_ref (pixbuf);
1516 }
1517
1518
1519 /**
1520 * gdk_pixbuf_new_from_stream_at_scale:
1521 * @stream: a #GInputStream to load the pixbuf from
1522 * @width: The width the image should have or -1 to not constrain the width
1523 * @height: The height the image should have or -1 to not constrain the height
1524 * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1525 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
1526 * @error: Return location for an error
1527 *
1528 * Creates a new pixbuf by loading an image from an input stream.
1529 *
1530 * The file format is detected automatically. If %NULL is returned, then
1531 * @error will be set. The @cancellable can be used to abort the operation
1532 * from another thread. If the operation was cancelled, the error
1533 * %G_IO_ERROR_CANCELLED will be returned. Other possible errors are in
1534 * the #GDK_PIXBUF_ERROR and %G_IO_ERROR domains.
1535 *
1536 * The image will be scaled to fit in the requested size, optionally
1537 * preserving the image's aspect ratio.
1538 *
1539 * When preserving the aspect ratio, a @width of -1 will cause the image to be
1540 * scaled to the exact given height, and a @height of -1 will cause the image
1541 * to be scaled to the exact given width. If both @width and @height are
1542 * given, this function will behave as if the smaller of the two values
1543 * is passed as -1.
1544 *
1545 * When not preserving aspect ratio, a @width or @height of -1 means to not
1546 * scale the image at all in that dimension.
1547 *
1548 * The stream is not closed.
1549 *
1550 * Return value: A newly-created pixbuf, or %NULL if any of several error
1551 * conditions occurred: the file could not be opened, the image format is
1552 * not supported, there was not enough memory to allocate the image buffer,
1553 * the stream contained invalid data, or the operation was cancelled.
1554 *
1555 * Since: 2.14
1556 */
1557 GdkPixbuf *
gdk_pixbuf_new_from_stream_at_scale(GInputStream * stream,gint width,gint height,gboolean preserve_aspect_ratio,GCancellable * cancellable,GError ** error)1558 gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
1559 gint width,
1560 gint height,
1561 gboolean preserve_aspect_ratio,
1562 GCancellable *cancellable,
1563 GError **error)
1564 {
1565 GdkPixbufLoader *loader;
1566 GdkPixbuf *pixbuf;
1567 AtScaleData info;
1568
1569 loader = gdk_pixbuf_loader_new ();
1570 info.width = width;
1571 info.height = height;
1572 info.preserve_aspect_ratio = preserve_aspect_ratio;
1573
1574 g_signal_connect (loader, "size-prepared",
1575 G_CALLBACK (at_scale_size_prepared_cb), &info);
1576
1577 pixbuf = load_from_stream (loader, stream, cancellable, error);
1578 g_object_unref (loader);
1579
1580 return pixbuf;
1581 }
1582
1583
1584 static void
load_from_stream_async_cb(GObject * stream,GAsyncResult * res,gpointer data)1585 load_from_stream_async_cb (GObject *stream,
1586 GAsyncResult *res,
1587 gpointer data)
1588 {
1589 GTask *task = data;
1590 GdkPixbufLoader *loader;
1591 GdkPixbuf *pixbuf;
1592 GError *error = NULL;
1593 GBytes *bytes = NULL;
1594
1595 loader = g_task_get_task_data (task);
1596
1597 bytes = g_input_stream_read_bytes_finish (G_INPUT_STREAM (stream), res, &error);
1598
1599 if (bytes == NULL) {
1600 gdk_pixbuf_loader_close (loader, NULL);
1601 g_task_return_error (task, error);
1602 } else if (g_bytes_get_size (bytes) > 0) {
1603 if (!gdk_pixbuf_loader_write (loader,
1604 g_bytes_get_data (bytes, NULL),
1605 g_bytes_get_size (bytes),
1606 &error)) {
1607 gdk_pixbuf_loader_close (loader, NULL);
1608 g_task_return_error (task, error);
1609 goto out;
1610 }
1611 g_input_stream_read_bytes_async (G_INPUT_STREAM (stream),
1612 LOAD_BUFFER_SIZE,
1613 G_PRIORITY_DEFAULT,
1614 g_task_get_cancellable (task),
1615 load_from_stream_async_cb,
1616 g_object_ref (task));
1617
1618 } else {
1619 if (!gdk_pixbuf_loader_close (loader, &error)) {
1620 g_task_return_error (task, error);
1621 goto out;
1622 }
1623
1624 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1625 g_task_return_pointer (task, g_object_ref (pixbuf), g_object_unref);
1626 }
1627
1628 out:
1629 g_bytes_unref (bytes);
1630 g_object_unref (task);
1631 }
1632
1633
1634 /**
1635 * gdk_pixbuf_new_from_stream_at_scale_async:
1636 * @stream: a #GInputStream from which to load the pixbuf
1637 * @width: the width the image should have or -1 to not constrain the width
1638 * @height: the height the image should have or -1 to not constrain the height
1639 * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1640 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
1641 * @callback: a #GAsyncReadyCallback to call when the pixbuf is loaded
1642 * @user_data: the data to pass to the callback function
1643 *
1644 * Creates a new pixbuf by asynchronously loading an image from an input stream.
1645 *
1646 * For more details see gdk_pixbuf_new_from_stream_at_scale(), which is the synchronous
1647 * version of this function.
1648 *
1649 * When the operation is finished, @callback will be called in the main thread.
1650 * You can then call gdk_pixbuf_new_from_stream_finish() to get the result of the operation.
1651 *
1652 * Since: 2.24
1653 **/
1654 void
gdk_pixbuf_new_from_stream_at_scale_async(GInputStream * stream,gint width,gint height,gboolean preserve_aspect_ratio,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1655 gdk_pixbuf_new_from_stream_at_scale_async (GInputStream *stream,
1656 gint width,
1657 gint height,
1658 gboolean preserve_aspect_ratio,
1659 GCancellable *cancellable,
1660 GAsyncReadyCallback callback,
1661 gpointer user_data)
1662 {
1663 GTask *task;
1664 AtScaleData *data;
1665 GdkPixbufLoader *loader;
1666
1667 g_return_if_fail (G_IS_INPUT_STREAM (stream));
1668 g_return_if_fail (callback != NULL);
1669 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
1670
1671 data = g_slice_new (AtScaleData);
1672 data->width = width;
1673 data->height = height;
1674 data->preserve_aspect_ratio = preserve_aspect_ratio;
1675
1676 loader = gdk_pixbuf_loader_new ();
1677 g_signal_connect (loader, "size-prepared",
1678 G_CALLBACK (at_scale_size_prepared_cb), data);
1679 g_object_set_data_full (G_OBJECT (loader),
1680 "gdk-pixbuf-please-kill-me-later",
1681 data,
1682 (GDestroyNotify) at_scale_data_async_data_free);
1683
1684 task = g_task_new (stream, cancellable, callback, user_data);
1685 g_task_set_source_tag (task, gdk_pixbuf_new_from_stream_at_scale_async);
1686 g_task_set_task_data (task, loader, g_object_unref);
1687
1688 g_input_stream_read_bytes_async (stream,
1689 LOAD_BUFFER_SIZE,
1690 G_PRIORITY_DEFAULT,
1691 cancellable,
1692 load_from_stream_async_cb,
1693 task);
1694 }
1695
1696 /**
1697 * gdk_pixbuf_new_from_stream:
1698 * @stream: a #GInputStream to load the pixbuf from
1699 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
1700 * @error: Return location for an error
1701 *
1702 * Creates a new pixbuf by loading an image from an input stream.
1703 *
1704 * The file format is detected automatically. If %NULL is returned, then
1705 * @error will be set. The @cancellable can be used to abort the operation
1706 * from another thread. If the operation was cancelled, the error
1707 * %G_IO_ERROR_CANCELLED will be returned. Other possible errors are in
1708 * the #GDK_PIXBUF_ERROR and %G_IO_ERROR domains.
1709 *
1710 * The stream is not closed.
1711 *
1712 * Return value: A newly-created pixbuf, or %NULL if any of several error
1713 * conditions occurred: the file could not be opened, the image format is
1714 * not supported, there was not enough memory to allocate the image buffer,
1715 * the stream contained invalid data, or the operation was cancelled.
1716 *
1717 * Since: 2.14
1718 **/
1719 GdkPixbuf *
gdk_pixbuf_new_from_stream(GInputStream * stream,GCancellable * cancellable,GError ** error)1720 gdk_pixbuf_new_from_stream (GInputStream *stream,
1721 GCancellable *cancellable,
1722 GError **error)
1723 {
1724 GdkPixbuf *pixbuf;
1725 GdkPixbufLoader *loader;
1726
1727 loader = gdk_pixbuf_loader_new ();
1728 pixbuf = load_from_stream (loader, stream, cancellable, error);
1729 g_object_unref (loader);
1730
1731 return pixbuf;
1732 }
1733
1734 GdkPixbuf *
_gdk_pixbuf_new_from_resource_try_pixdata(const char * resource_path)1735 _gdk_pixbuf_new_from_resource_try_pixdata (const char *resource_path)
1736 {
1737 gsize data_size;
1738 GBytes *bytes;
1739
1740 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1741 /* We specialize GdkPixdata files, making these a reference to the
1742 * compiled-in resource data, whether uncompressed and mmap'ed, or
1743 * compressed, and uncompressed on-the-fly.
1744 */
1745 if (g_resources_get_info (resource_path, 0, &data_size, NULL, NULL) &&
1746 data_size > sizeof(guint32) &&
1747 (bytes = g_resources_lookup_data (resource_path, 0, NULL)) != NULL) {
1748 GdkPixbuf*pixbuf = NULL;
1749 const guint8 *stream = g_bytes_get_data (bytes, NULL);
1750 GdkPixdata pixdata;
1751 guint32 magic;
1752
1753 magic = (stream[0] << 24) + (stream[1] << 16) + (stream[2] << 8) + stream[3];
1754 if (magic == GDK_PIXBUF_MAGIC_NUMBER &&
1755 gdk_pixdata_deserialize (&pixdata, data_size, stream, NULL)) {
1756 pixbuf = gdk_pixbuf_from_pixdata (&pixdata, FALSE, NULL);
1757 }
1758
1759 if (pixbuf) {
1760 /* Free the GBytes with the pixbuf */
1761 g_object_set_data_full (G_OBJECT (pixbuf), "gdk-pixbuf-resource-bytes", bytes, (GDestroyNotify) g_bytes_unref);
1762 return pixbuf;
1763 } else {
1764 g_bytes_unref (bytes);
1765 }
1766 }
1767 G_GNUC_END_IGNORE_DEPRECATIONS
1768
1769 return NULL;
1770 }
1771
1772 /**
1773 * gdk_pixbuf_new_from_resource:
1774 * @resource_path: the path of the resource file
1775 * @error: Return location for an error
1776 *
1777 * Creates a new pixbuf by loading an image from an resource.
1778 *
1779 * The file format is detected automatically. If %NULL is returned, then
1780 * @error will be set.
1781 *
1782 * Return value: A newly-created pixbuf, or %NULL if any of several error
1783 * conditions occurred: the file could not be opened, the image format is
1784 * not supported, there was not enough memory to allocate the image buffer,
1785 * the stream contained invalid data, or the operation was cancelled.
1786 *
1787 * Since: 2.26
1788 **/
1789 GdkPixbuf *
gdk_pixbuf_new_from_resource(const gchar * resource_path,GError ** error)1790 gdk_pixbuf_new_from_resource (const gchar *resource_path,
1791 GError **error)
1792 {
1793 GInputStream *stream;
1794 GdkPixbuf *pixbuf;
1795
1796 pixbuf = _gdk_pixbuf_new_from_resource_try_pixdata (resource_path);
1797 if (pixbuf)
1798 return pixbuf;
1799
1800 stream = g_resources_open_stream (resource_path, 0, error);
1801 if (stream == NULL)
1802 return NULL;
1803
1804 pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, error);
1805 g_object_unref (stream);
1806 return pixbuf;
1807 }
1808
1809 /**
1810 * gdk_pixbuf_new_from_resource_at_scale:
1811 * @resource_path: the path of the resource file
1812 * @width: The width the image should have or -1 to not constrain the width
1813 * @height: The height the image should have or -1 to not constrain the height
1814 * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1815 * @error: Return location for an error
1816 *
1817 * Creates a new pixbuf by loading an image from an resource.
1818 *
1819 * The file format is detected automatically. If %NULL is returned, then
1820 * @error will be set.
1821 *
1822 * The image will be scaled to fit in the requested size, optionally
1823 * preserving the image's aspect ratio. When preserving the aspect ratio,
1824 * a @width of -1 will cause the image to be scaled to the exact given
1825 * height, and a @height of -1 will cause the image to be scaled to the
1826 * exact given width. When not preserving aspect ratio, a @width or
1827 * @height of -1 means to not scale the image at all in that dimension.
1828 *
1829 * The stream is not closed.
1830 *
1831 * Return value: A newly-created pixbuf, or %NULL if any of several error
1832 * conditions occurred: the file could not be opened, the image format is
1833 * not supported, there was not enough memory to allocate the image buffer,
1834 * the stream contained invalid data, or the operation was cancelled.
1835 *
1836 * Since: 2.26
1837 */
1838 GdkPixbuf *
gdk_pixbuf_new_from_resource_at_scale(const char * resource_path,int width,int height,gboolean preserve_aspect_ratio,GError ** error)1839 gdk_pixbuf_new_from_resource_at_scale (const char *resource_path,
1840 int width,
1841 int height,
1842 gboolean preserve_aspect_ratio,
1843 GError **error)
1844 {
1845 GInputStream *stream;
1846 GdkPixbuf *pixbuf;
1847
1848 stream = g_resources_open_stream (resource_path, 0, error);
1849 if (stream == NULL)
1850 return NULL;
1851
1852 pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, width, height, preserve_aspect_ratio, NULL, error);
1853 g_object_unref (stream);
1854 return pixbuf;
1855 }
1856
1857 /**
1858 * gdk_pixbuf_new_from_stream_async:
1859 * @stream: a #GInputStream from which to load the pixbuf
1860 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
1861 * @callback: a #GAsyncReadyCallback to call when the pixbuf is loaded
1862 * @user_data: the data to pass to the callback function
1863 *
1864 * Creates a new pixbuf by asynchronously loading an image from an input stream.
1865 *
1866 * For more details see gdk_pixbuf_new_from_stream(), which is the synchronous
1867 * version of this function.
1868 *
1869 * When the operation is finished, @callback will be called in the main thread.
1870 * You can then call gdk_pixbuf_new_from_stream_finish() to get the result of the operation.
1871 *
1872 * Since: 2.24
1873 **/
1874 void
gdk_pixbuf_new_from_stream_async(GInputStream * stream,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1875 gdk_pixbuf_new_from_stream_async (GInputStream *stream,
1876 GCancellable *cancellable,
1877 GAsyncReadyCallback callback,
1878 gpointer user_data)
1879 {
1880 GTask *task;
1881
1882 g_return_if_fail (G_IS_INPUT_STREAM (stream));
1883 g_return_if_fail (callback != NULL);
1884 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
1885
1886 task = g_task_new (stream, cancellable, callback, user_data);
1887 g_task_set_source_tag (task, gdk_pixbuf_new_from_stream_async);
1888 g_task_set_task_data (task, gdk_pixbuf_loader_new (), g_object_unref);
1889
1890 g_input_stream_read_bytes_async (stream,
1891 LOAD_BUFFER_SIZE,
1892 G_PRIORITY_DEFAULT,
1893 cancellable,
1894 load_from_stream_async_cb,
1895 task);
1896 }
1897
1898 /**
1899 * gdk_pixbuf_new_from_stream_finish:
1900 * @async_result: a #GAsyncResult
1901 * @error: a #GError, or %NULL
1902 *
1903 * Finishes an asynchronous pixbuf creation operation started with
1904 * gdk_pixbuf_new_from_stream_async().
1905 *
1906 * Return value: a #GdkPixbuf or %NULL on error. Free the returned
1907 * object with g_object_unref().
1908 *
1909 * Since: 2.24
1910 **/
1911 GdkPixbuf *
gdk_pixbuf_new_from_stream_finish(GAsyncResult * async_result,GError ** error)1912 gdk_pixbuf_new_from_stream_finish (GAsyncResult *async_result,
1913 GError **error)
1914 {
1915 GTask *task;
1916
1917 g_return_val_if_fail (G_IS_TASK (async_result), NULL);
1918 g_return_val_if_fail (!error || (error && !*error), NULL);
1919
1920 task = G_TASK (async_result);
1921
1922 g_warn_if_fail (g_task_get_source_tag (task) == gdk_pixbuf_new_from_stream_async ||
1923 g_task_get_source_tag (task) == gdk_pixbuf_new_from_stream_at_scale_async);
1924
1925 return g_task_propagate_pointer (task, error);
1926 }
1927
1928 static void
info_cb(GdkPixbufLoader * loader,int width,int height,gpointer data)1929 info_cb (GdkPixbufLoader *loader,
1930 int width,
1931 int height,
1932 gpointer data)
1933 {
1934 struct {
1935 GdkPixbufFormat *format;
1936 int width;
1937 int height;
1938 } *info = data;
1939
1940 g_return_if_fail (width > 0 && height > 0);
1941
1942 info->format = gdk_pixbuf_loader_get_format (loader);
1943 info->width = width;
1944 info->height = height;
1945
1946 gdk_pixbuf_loader_set_size (loader, 0, 0);
1947 }
1948
1949 /**
1950 * gdk_pixbuf_get_file_info:
1951 * @filename: (type filename): The name of the file to identify.
1952 * @width: (optional) (out): Return location for the width of the
1953 * image, or %NULL
1954 * @height: (optional) (out): Return location for the height of the
1955 * image, or %NULL
1956 *
1957 * Parses an image file far enough to determine its format and size.
1958 *
1959 * Returns: (nullable) (transfer none): A #GdkPixbufFormat describing
1960 * the image format of the file or %NULL if the image format wasn't
1961 * recognized. The return value is owned by #GdkPixbuf and should
1962 * not be freed.
1963 *
1964 * Since: 2.4
1965 **/
1966 GdkPixbufFormat *
gdk_pixbuf_get_file_info(const gchar * filename,gint * width,gint * height)1967 gdk_pixbuf_get_file_info (const gchar *filename,
1968 gint *width,
1969 gint *height)
1970 {
1971 GdkPixbufLoader *loader;
1972 guchar buffer[SNIFF_BUFFER_SIZE];
1973 int length;
1974 FILE *f;
1975 struct {
1976 GdkPixbufFormat *format;
1977 gint width;
1978 gint height;
1979 } info;
1980
1981 g_return_val_if_fail (filename != NULL, NULL);
1982
1983 f = g_fopen (filename, "rb");
1984 if (!f)
1985 return NULL;
1986
1987 loader = _gdk_pixbuf_loader_new_with_filename (filename);
1988
1989 info.format = NULL;
1990 info.width = -1;
1991 info.height = -1;
1992
1993 g_signal_connect (loader, "size-prepared", G_CALLBACK (info_cb), &info);
1994
1995 while (!feof (f) && !ferror (f)) {
1996 length = fread (buffer, 1, sizeof (buffer), f);
1997 if (length > 0) {
1998 if (!gdk_pixbuf_loader_write (loader, buffer, length, NULL))
1999 break;
2000 }
2001 if (info.format != NULL)
2002 break;
2003 }
2004
2005 fclose (f);
2006 gdk_pixbuf_loader_close (loader, NULL);
2007 g_object_unref (loader);
2008
2009 if (width)
2010 *width = info.width;
2011 if (height)
2012 *height = info.height;
2013
2014 return info.format;
2015 }
2016
2017 typedef struct {
2018 gchar *filename;
2019 gint width;
2020 gint height;
2021 } GetFileInfoAsyncData;
2022
2023 static void
get_file_info_async_data_free(GetFileInfoAsyncData * data)2024 get_file_info_async_data_free (GetFileInfoAsyncData *data)
2025 {
2026 g_free (data->filename);
2027 g_slice_free (GetFileInfoAsyncData, data);
2028 }
2029
2030 static void
get_file_info_thread(GTask * task,gpointer source_object,GetFileInfoAsyncData * data,GCancellable * cancellable)2031 get_file_info_thread (GTask *task,
2032 gpointer source_object,
2033 GetFileInfoAsyncData *data,
2034 GCancellable *cancellable)
2035 {
2036 GdkPixbufFormat *format;
2037
2038 format = gdk_pixbuf_get_file_info (data->filename, &data->width, &data->height);
2039 if (format == NULL) {
2040 g_task_return_new_error (task,
2041 GDK_PIXBUF_ERROR,
2042 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
2043 "Failed to recognize image format");
2044 } else {
2045 g_task_return_pointer (task,
2046 gdk_pixbuf_format_copy (format),
2047 (GDestroyNotify) gdk_pixbuf_format_free);
2048 }
2049 }
2050
2051 /**
2052 * gdk_pixbuf_get_file_info_async:
2053 * @filename: (type filename): The name of the file to identify
2054 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
2055 * @callback: a #GAsyncReadyCallback to call when the file info is available
2056 * @user_data: the data to pass to the callback function
2057 *
2058 * Asynchronously parses an image file far enough to determine its
2059 * format and size.
2060 *
2061 * For more details see gdk_pixbuf_get_file_info(), which is the synchronous
2062 * version of this function.
2063 *
2064 * When the operation is finished, @callback will be called in the
2065 * main thread. You can then call gdk_pixbuf_get_file_info_finish() to
2066 * get the result of the operation.
2067 *
2068 * Since: 2.32
2069 **/
2070 void
gdk_pixbuf_get_file_info_async(const gchar * filename,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2071 gdk_pixbuf_get_file_info_async (const gchar *filename,
2072 GCancellable *cancellable,
2073 GAsyncReadyCallback callback,
2074 gpointer user_data)
2075 {
2076 GetFileInfoAsyncData *data;
2077 GTask *task;
2078
2079 g_return_if_fail (filename != NULL);
2080 g_return_if_fail (callback != NULL);
2081 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
2082
2083 data = g_slice_new0 (GetFileInfoAsyncData);
2084 data->filename = g_strdup (filename);
2085
2086 task = g_task_new (NULL, cancellable, callback, user_data);
2087 g_task_set_return_on_cancel (task, TRUE);
2088 g_task_set_source_tag (task, gdk_pixbuf_get_file_info_async);
2089 g_task_set_task_data (task, data, (GDestroyNotify) get_file_info_async_data_free);
2090 g_task_run_in_thread (task, (GTaskThreadFunc) get_file_info_thread);
2091 g_object_unref (task);
2092 }
2093
2094 /**
2095 * gdk_pixbuf_get_file_info_finish:
2096 * @async_result: a #GAsyncResult
2097 * @width: (out): Return location for the width of the image, or %NULL
2098 * @height: (out): Return location for the height of the image, or %NULL
2099 * @error: a #GError, or %NULL
2100 *
2101 * Finishes an asynchronous pixbuf parsing operation started with
2102 * gdk_pixbuf_get_file_info_async().
2103 *
2104 * Returns: (transfer none): A #GdkPixbufFormat describing the image
2105 * format of the file or %NULL if the image format wasn't
2106 * recognized. The return value is owned by GdkPixbuf and should
2107 * not be freed.
2108 *
2109 * Since: 2.32
2110 **/
2111 GdkPixbufFormat *
gdk_pixbuf_get_file_info_finish(GAsyncResult * async_result,gint * width,gint * height,GError ** error)2112 gdk_pixbuf_get_file_info_finish (GAsyncResult *async_result,
2113 gint *width,
2114 gint *height,
2115 GError **error)
2116 {
2117 GetFileInfoAsyncData *data;
2118 GTask *task;
2119
2120 g_return_val_if_fail (g_task_is_valid (async_result, NULL), NULL);
2121
2122 task = G_TASK (async_result);
2123
2124 g_return_val_if_fail (!error || (error && !*error), NULL);
2125 g_warn_if_fail (g_task_get_source_tag (task) == gdk_pixbuf_get_file_info_async);
2126
2127 data = g_task_get_task_data (task);
2128
2129 if (!g_task_had_error (task)) {
2130 if (width)
2131 *width = data->width;
2132 if (height)
2133 *height = data->height;
2134 }
2135
2136 return g_task_propagate_pointer (task, error);
2137 }
2138
2139 /**
2140 * gdk_pixbuf_new_from_xpm_data:
2141 * @data: (array zero-terminated=1): Pointer to inline XPM data.
2142 *
2143 * Creates a new pixbuf by parsing XPM data in memory. This data is commonly
2144 * the result of including an XPM file into a program's C source.
2145 *
2146 * Return value: A newly-created pixbuf with a reference count of 1.
2147 **/
2148 GdkPixbuf *
gdk_pixbuf_new_from_xpm_data(const char ** data)2149 gdk_pixbuf_new_from_xpm_data (const char **data)
2150 {
2151 GdkPixbuf *(* load_xpm_data) (const char **data);
2152 GdkPixbuf *pixbuf;
2153 GError *error = NULL;
2154 GdkPixbufModule *xpm_module;
2155
2156 g_return_val_if_fail (data != NULL, NULL);
2157
2158 xpm_module = _gdk_pixbuf_get_named_module ("xpm", &error);
2159 if (xpm_module == NULL) {
2160 g_warning ("Error loading XPM image loader: %s", error->message);
2161 g_error_free (error);
2162 return NULL;
2163 }
2164
2165 if (!_gdk_pixbuf_load_module (xpm_module, &error)) {
2166 g_warning ("Error loading XPM image loader: %s", error->message);
2167 g_error_free (error);
2168 return NULL;
2169 }
2170
2171 if (xpm_module->load_xpm_data == NULL) {
2172 g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
2173 pixbuf = NULL;
2174 } else {
2175 load_xpm_data = xpm_module->load_xpm_data;
2176 pixbuf = (* load_xpm_data) (data);
2177 }
2178
2179 return pixbuf;
2180 }
2181
2182 static void
collect_save_options(va_list opts,gchar *** keys,gchar *** vals)2183 collect_save_options (va_list opts,
2184 gchar ***keys,
2185 gchar ***vals)
2186 {
2187 gchar *key;
2188 gchar *val;
2189 gchar *next;
2190 gint count;
2191
2192 count = 0;
2193 *keys = NULL;
2194 *vals = NULL;
2195
2196 next = va_arg (opts, gchar*);
2197 while (next)
2198 {
2199 key = next;
2200 val = va_arg (opts, gchar*);
2201
2202 ++count;
2203
2204 /* woo, slow */
2205 *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
2206 *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
2207
2208 (*keys)[count-1] = g_strdup (key);
2209 (*vals)[count-1] = g_strdup (val);
2210
2211 (*keys)[count] = NULL;
2212 (*vals)[count] = NULL;
2213
2214 next = va_arg (opts, gchar*);
2215 }
2216 }
2217
2218 static gboolean
save_to_file_callback(const gchar * buf,gsize count,GError ** error,gpointer data)2219 save_to_file_callback (const gchar *buf,
2220 gsize count,
2221 GError **error,
2222 gpointer data)
2223 {
2224 FILE *filehandle = data;
2225 gsize n;
2226
2227 n = fwrite (buf, 1, count, filehandle);
2228 if (n != count) {
2229 gint save_errno = errno;
2230 g_set_error (error,
2231 G_FILE_ERROR,
2232 g_file_error_from_errno (save_errno),
2233 _("Error writing to image file: %s"),
2234 g_strerror (save_errno));
2235 return FALSE;
2236 }
2237 return TRUE;
2238 }
2239
2240 static gboolean
gdk_pixbuf_real_save(GdkPixbuf * pixbuf,FILE * filehandle,const char * type,gchar ** keys,gchar ** values,GError ** error)2241 gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
2242 FILE *filehandle,
2243 const char *type,
2244 gchar **keys,
2245 gchar **values,
2246 GError **error)
2247 {
2248 gboolean ret;
2249 GdkPixbufModule *image_module = NULL;
2250
2251 image_module = _gdk_pixbuf_get_named_module (type, error);
2252
2253 if (image_module == NULL)
2254 return FALSE;
2255
2256 if (!_gdk_pixbuf_load_module (image_module, error))
2257 return FALSE;
2258
2259 if (image_module->save) {
2260 /* save normally */
2261 ret = (* image_module->save) (filehandle, pixbuf,
2262 keys, values,
2263 error);
2264 } else if (image_module->save_to_callback) {
2265 /* save with simple callback */
2266 ret = (* image_module->save_to_callback) (save_to_file_callback,
2267 filehandle, pixbuf,
2268 keys, values,
2269 error);
2270 } else {
2271 /* can't save */
2272 g_set_error (error,
2273 GDK_PIXBUF_ERROR,
2274 GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
2275 _("This build of gdk-pixbuf does not support saving the image format: %s"),
2276 type);
2277 ret = FALSE;
2278 }
2279
2280 return ret;
2281 }
2282
2283 #define TMP_FILE_BUF_SIZE 4096
2284
2285 static gboolean
save_to_callback_with_tmp_file(GdkPixbufModule * image_module,GdkPixbuf * pixbuf,GdkPixbufSaveFunc save_func,gpointer user_data,gchar ** keys,gchar ** values,GError ** error)2286 save_to_callback_with_tmp_file (GdkPixbufModule *image_module,
2287 GdkPixbuf *pixbuf,
2288 GdkPixbufSaveFunc save_func,
2289 gpointer user_data,
2290 gchar **keys,
2291 gchar **values,
2292 GError **error)
2293 {
2294 int fd;
2295 FILE *f = NULL;
2296 gboolean retval = FALSE;
2297 gchar *buf = NULL;
2298 gsize n;
2299 gchar *filename = NULL;
2300
2301 buf = g_try_malloc (TMP_FILE_BUF_SIZE);
2302 if (buf == NULL) {
2303 g_set_error_literal (error,
2304 GDK_PIXBUF_ERROR,
2305 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2306 _("Insufficient memory to save image to callback"));
2307 goto end;
2308 }
2309
2310 fd = g_file_open_tmp ("gdkpixbuf-save-tmp.XXXXXX", &filename, error);
2311 if (fd == -1)
2312 goto end;
2313 f = fdopen (fd, "wb+");
2314 if (f == NULL) {
2315 gint save_errno = errno;
2316 g_set_error_literal (error,
2317 G_FILE_ERROR,
2318 g_file_error_from_errno (save_errno),
2319 _("Failed to open temporary file"));
2320 goto end;
2321 }
2322
2323 retval = (image_module->save) (f, pixbuf, keys, values, error);
2324 if (!retval)
2325 goto end;
2326
2327 rewind (f);
2328 for (;;) {
2329 n = fread (buf, 1, TMP_FILE_BUF_SIZE, f);
2330 if (n > 0) {
2331 if (!save_func (buf, n, error, user_data))
2332 goto end;
2333 }
2334 if (n != TMP_FILE_BUF_SIZE)
2335 break;
2336 }
2337 if (ferror (f)) {
2338 gint save_errno = errno;
2339 g_set_error_literal (error,
2340 G_FILE_ERROR,
2341 g_file_error_from_errno (save_errno),
2342 _("Failed to read from temporary file"));
2343 goto end;
2344 }
2345 retval = TRUE;
2346
2347 end:
2348 /* cleanup and return retval */
2349 if (f)
2350 fclose (f);
2351 if (filename) {
2352 g_unlink (filename);
2353 g_free (filename);
2354 }
2355 g_free (buf);
2356
2357 return retval;
2358 }
2359
2360 static gboolean
gdk_pixbuf_real_save_to_callback(GdkPixbuf * pixbuf,GdkPixbufSaveFunc save_func,gpointer user_data,const char * type,gchar ** keys,gchar ** values,GError ** error)2361 gdk_pixbuf_real_save_to_callback (GdkPixbuf *pixbuf,
2362 GdkPixbufSaveFunc save_func,
2363 gpointer user_data,
2364 const char *type,
2365 gchar **keys,
2366 gchar **values,
2367 GError **error)
2368 {
2369 gboolean ret;
2370 GdkPixbufModule *image_module = NULL;
2371
2372 image_module = _gdk_pixbuf_get_named_module (type, error);
2373
2374 if (image_module == NULL)
2375 return FALSE;
2376
2377 if (!_gdk_pixbuf_load_module (image_module, error))
2378 return FALSE;
2379
2380 if (image_module->save_to_callback) {
2381 /* save normally */
2382 ret = (* image_module->save_to_callback) (save_func, user_data,
2383 pixbuf, keys, values,
2384 error);
2385 } else if (image_module->save) {
2386 /* use a temporary file */
2387 ret = save_to_callback_with_tmp_file (image_module, pixbuf,
2388 save_func, user_data,
2389 keys, values,
2390 error);
2391 } else {
2392 /* can't save */
2393 g_set_error (error,
2394 GDK_PIXBUF_ERROR,
2395 GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
2396 _("This build of gdk-pixbuf does not support saving the image format: %s"),
2397 type);
2398 ret = FALSE;
2399 }
2400
2401 return ret;
2402 }
2403
2404
2405 /**
2406 * gdk_pixbuf_save:
2407 * @pixbuf: a #GdkPixbuf.
2408 * @filename: (type filename): name of file to save.
2409 * @type: name of file format.
2410 * @error: (allow-none): return location for error, or %NULL
2411 * @...: list of key-value save options, followed by %NULL
2412 *
2413 * Saves pixbuf to a file in format @type. By default, "jpeg", "png", "ico"
2414 * and "bmp" are possible file formats to save in, but more formats may be
2415 * installed. The list of all writable formats can be determined in the
2416 * following way:
2417 *
2418 * |[
2419 * void add_if_writable (GdkPixbufFormat *data, GSList **list)
2420 * {
2421 * if (gdk_pixbuf_format_is_writable (data))
2422 * *list = g_slist_prepend (*list, data);
2423 * }
2424 *
2425 * GSList *formats = gdk_pixbuf_get_formats ();
2426 * GSList *writable_formats = NULL;
2427 * g_slist_foreach (formats, add_if_writable, &writable_formats);
2428 * g_slist_free (formats);
2429 * ]|
2430 *
2431 * If @error is set, %FALSE will be returned. Possible errors include
2432 * those in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
2433 *
2434 * The variable argument list should be %NULL-terminated; if not empty,
2435 * it should contain pairs of strings that modify the save
2436 * parameters. For example:
2437 * |[
2438 * gdk_pixbuf_save (pixbuf, handle, "jpeg", &error, "quality", "100", NULL);
2439 * ]|
2440 *
2441 * Currently only few parameters exist. JPEG images can be saved with a
2442 * "quality" parameter; its value should be in the range [0,100]. JPEG
2443 * and PNG density can be set by setting the "x-dpi" and "y-dpi" parameters
2444 * to the appropriate values in dots per inch.
2445 *
2446 * Text chunks can be attached to PNG images by specifying parameters of
2447 * the form "tEXt::key", where key is an ASCII string of length 1-79.
2448 * The values are UTF-8 encoded strings. The PNG compression level can
2449 * be specified using the "compression" parameter; it's value is in an
2450 * integer in the range of [0,9].
2451 *
2452 * ICC color profiles can also be embedded into PNG, JPEG and TIFF images.
2453 * The "icc-profile" value should be the complete ICC profile encoded
2454 * into base64.
2455 *
2456 * |[
2457 * gchar *contents;
2458 * gchar *contents_encode;
2459 * gsize length;
2460 * g_file_get_contents ("/home/hughsie/.color/icc/L225W.icm", &contents, &length, NULL);
2461 * contents_encode = g_base64_encode ((const guchar *) contents, length);
2462 * gdk_pixbuf_save (pixbuf, handle, "png", &error, "icc-profile", contents_encode, NULL);
2463 * ]|
2464 *
2465 * TIFF images recognize: (1) a "bits-per-sample" option (integer) which
2466 * can be either 1 for saving bi-level CCITTFAX4 images, or 8 for saving
2467 * 8-bits per sample; (2) a "compression" option (integer) which can be
2468 * 1 for no compression, 2 for Huffman, 5 for LZW, 7 for JPEG and 8 for
2469 * DEFLATE (see the libtiff documentation and tiff.h for all supported
2470 * codec values); (3) an "icc-profile" option (zero-terminated string)
2471 * containing a base64 encoded ICC color profile.
2472 *
2473 * ICO images can be saved in depth 16, 24, or 32, by using the "depth"
2474 * parameter. When the ICO saver is given "x_hot" and "y_hot" parameters,
2475 * it produces a CUR instead of an ICO.
2476 *
2477 * Return value: whether an error was set
2478 **/
2479 gboolean
gdk_pixbuf_save(GdkPixbuf * pixbuf,const char * filename,const char * type,GError ** error,...)2480 gdk_pixbuf_save (GdkPixbuf *pixbuf,
2481 const char *filename,
2482 const char *type,
2483 GError **error,
2484 ...)
2485 {
2486 gchar **keys = NULL;
2487 gchar **values = NULL;
2488 va_list args;
2489 gboolean result;
2490
2491 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2492
2493 va_start (args, error);
2494
2495 collect_save_options (args, &keys, &values);
2496
2497 va_end (args);
2498
2499 result = gdk_pixbuf_savev (pixbuf, filename, type,
2500 keys, values,
2501 error);
2502
2503 g_strfreev (keys);
2504 g_strfreev (values);
2505
2506 return result;
2507 }
2508
2509 /**
2510 * gdk_pixbuf_savev:
2511 * @pixbuf: a #GdkPixbuf.
2512 * @filename: (type filename): name of file to save.
2513 * @type: name of file format.
2514 * @option_keys: (array zero-terminated=1): name of options to set, %NULL-terminated
2515 * @option_values: (array zero-terminated=1): values for named options
2516 * @error: (allow-none): return location for error, or %NULL
2517 *
2518 * Saves pixbuf to a file in @type, which is currently "jpeg", "png", "tiff", "ico" or "bmp".
2519 * If @error is set, %FALSE will be returned.
2520 * See gdk_pixbuf_save () for more details.
2521 *
2522 * Return value: whether an error was set
2523 **/
2524
2525 gboolean
gdk_pixbuf_savev(GdkPixbuf * pixbuf,const char * filename,const char * type,char ** option_keys,char ** option_values,GError ** error)2526 gdk_pixbuf_savev (GdkPixbuf *pixbuf,
2527 const char *filename,
2528 const char *type,
2529 char **option_keys,
2530 char **option_values,
2531 GError **error)
2532 {
2533 FILE *f = NULL;
2534 gboolean result;
2535
2536 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
2537 g_return_val_if_fail (gdk_pixbuf_get_width (pixbuf) >= 0, FALSE);
2538 g_return_val_if_fail (gdk_pixbuf_get_height (pixbuf) >= 0, FALSE);
2539 g_return_val_if_fail (gdk_pixbuf_get_n_channels (pixbuf) >= 0, FALSE);
2540 g_return_val_if_fail (filename != NULL, FALSE);
2541 g_return_val_if_fail (type != NULL, FALSE);
2542 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2543
2544 f = g_fopen (filename, "wb");
2545
2546 if (f == NULL) {
2547 gint save_errno = errno;
2548 gchar *display_name = g_filename_display_name (filename);
2549 g_set_error (error,
2550 G_FILE_ERROR,
2551 g_file_error_from_errno (save_errno),
2552 _("Failed to open “%s” for writing: %s"),
2553 display_name,
2554 g_strerror (save_errno));
2555 g_free (display_name);
2556 return FALSE;
2557 }
2558
2559
2560 result = gdk_pixbuf_real_save (pixbuf, f, type,
2561 option_keys, option_values,
2562 error);
2563
2564
2565 if (!result) {
2566 g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
2567 fclose (f);
2568 g_unlink (filename);
2569 return FALSE;
2570 }
2571
2572 if (fclose (f) < 0) {
2573 gint save_errno = errno;
2574 gchar *display_name = g_filename_display_name (filename);
2575 g_set_error (error,
2576 G_FILE_ERROR,
2577 g_file_error_from_errno (save_errno),
2578 _("Failed to close “%s” while writing image, all data may not have been saved: %s"),
2579 display_name,
2580 g_strerror (save_errno));
2581 g_free (display_name);
2582 return FALSE;
2583 }
2584
2585 return TRUE;
2586 }
2587
2588 #ifdef G_OS_WIN32
2589
2590 /**
2591 * gdk_pixbuf_savev_utf8:
2592 * @pixbuf: a #GdkPixbuf.
2593 * @filename: name of file to save.
2594 * @type: name of file format.
2595 * @option_keys: (array zero-terminated=1): name of options to set, %NULL-terminated
2596 * @option_values: (array zero-terminated=1): values for named options
2597 * @error: (allow-none): return location for error, or %NULL
2598 *
2599 * Same as gdk_pixbuf_savev()
2600 *
2601 * Return value: whether an error was set
2602 **/
2603 gboolean
gdk_pixbuf_savev_utf8(GdkPixbuf * pixbuf,const char * filename,const char * type,char ** option_keys,char ** option_values,GError ** error)2604 gdk_pixbuf_savev_utf8 (GdkPixbuf *pixbuf,
2605 const char *filename,
2606 const char *type,
2607 char **option_keys,
2608 char **option_values,
2609 GError **error)
2610 {
2611 return gdk_pixbuf_savev (pixbuf, filename, type, option_keys,
2612 option_values, error);
2613 }
2614
2615 #endif
2616
2617 /**
2618 * gdk_pixbuf_save_to_callback:
2619 * @pixbuf: a #GdkPixbuf.
2620 * @save_func: (scope call): a function that is called to save each block of data that
2621 * the save routine generates.
2622 * @user_data: user data to pass to the save function.
2623 * @type: name of file format.
2624 * @error: (allow-none): return location for error, or %NULL
2625 * @...: list of key-value save options
2626 *
2627 * Saves pixbuf in format @type by feeding the produced data to a
2628 * callback. Can be used when you want to store the image to something
2629 * other than a file, such as an in-memory buffer or a socket.
2630 * If @error is set, %FALSE will be returned. Possible errors
2631 * include those in the #GDK_PIXBUF_ERROR domain and whatever the save
2632 * function generates.
2633 *
2634 * See gdk_pixbuf_save() for more details.
2635 *
2636 * Return value: whether an error was set
2637 *
2638 * Since: 2.4
2639 **/
2640 gboolean
gdk_pixbuf_save_to_callback(GdkPixbuf * pixbuf,GdkPixbufSaveFunc save_func,gpointer user_data,const char * type,GError ** error,...)2641 gdk_pixbuf_save_to_callback (GdkPixbuf *pixbuf,
2642 GdkPixbufSaveFunc save_func,
2643 gpointer user_data,
2644 const char *type,
2645 GError **error,
2646 ...)
2647 {
2648 gchar **keys = NULL;
2649 gchar **values = NULL;
2650 va_list args;
2651 gboolean result;
2652
2653 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2654
2655 va_start (args, error);
2656
2657 collect_save_options (args, &keys, &values);
2658
2659 va_end (args);
2660
2661 result = gdk_pixbuf_save_to_callbackv (pixbuf, save_func, user_data,
2662 type, keys, values,
2663 error);
2664
2665 g_strfreev (keys);
2666 g_strfreev (values);
2667
2668 return result;
2669 }
2670
2671 /**
2672 * gdk_pixbuf_save_to_callbackv:
2673 * @pixbuf: a #GdkPixbuf.
2674 * @save_func: (scope call): a function that is called to save each block of data that
2675 * the save routine generates.
2676 * @user_data: (closure): user data to pass to the save function.
2677 * @type: name of file format.
2678 * @option_keys: (array zero-terminated=1) (element-type utf8): name of options to set, %NULL-terminated
2679 * @option_values: (array zero-terminated=1) (element-type utf8): values for named options
2680 * @error: (allow-none): return location for error, or %NULL
2681 *
2682 * Saves pixbuf to a callback in format @type, which is currently "jpeg",
2683 * "png", "tiff", "ico" or "bmp". If @error is set, %FALSE will be returned. See
2684 * gdk_pixbuf_save_to_callback () for more details.
2685 *
2686 * Return value: whether an error was set
2687 *
2688 * Since: 2.4
2689 **/
2690 gboolean
gdk_pixbuf_save_to_callbackv(GdkPixbuf * pixbuf,GdkPixbufSaveFunc save_func,gpointer user_data,const char * type,char ** option_keys,char ** option_values,GError ** error)2691 gdk_pixbuf_save_to_callbackv (GdkPixbuf *pixbuf,
2692 GdkPixbufSaveFunc save_func,
2693 gpointer user_data,
2694 const char *type,
2695 char **option_keys,
2696 char **option_values,
2697 GError **error)
2698 {
2699 gboolean result;
2700
2701 g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
2702 g_return_val_if_fail (gdk_pixbuf_get_width (pixbuf) >= 0, FALSE);
2703 g_return_val_if_fail (gdk_pixbuf_get_height (pixbuf) >= 0, FALSE);
2704 g_return_val_if_fail (gdk_pixbuf_get_n_channels (pixbuf) >= 0, FALSE);
2705 g_return_val_if_fail (save_func != NULL, FALSE);
2706 g_return_val_if_fail (type != NULL, FALSE);
2707 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2708
2709 result = gdk_pixbuf_real_save_to_callback (pixbuf,
2710 save_func, user_data, type,
2711 option_keys, option_values,
2712 error);
2713
2714 if (!result) {
2715 g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
2716 return FALSE;
2717 }
2718
2719 return TRUE;
2720 }
2721
2722 /**
2723 * gdk_pixbuf_save_to_buffer:
2724 * @pixbuf: a #GdkPixbuf.
2725 * @buffer: (array length=buffer_size) (out) (element-type guint8): location to receive a pointer
2726 * to the new buffer.
2727 * @buffer_size: location to receive the size of the new buffer.
2728 * @type: name of file format.
2729 * @error: (allow-none): return location for error, or %NULL
2730 * @...: list of key-value save options
2731 *
2732 * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
2733 * "png", "tiff", "ico" or "bmp". This is a convenience function that uses
2734 * gdk_pixbuf_save_to_callback() to do the real work. Note that the buffer
2735 * is not nul-terminated and may contain embedded nuls.
2736 * If @error is set, %FALSE will be returned and @buffer will be set to
2737 * %NULL. Possible errors include those in the #GDK_PIXBUF_ERROR
2738 * domain.
2739 *
2740 * See gdk_pixbuf_save() for more details.
2741 *
2742 * Return value: whether an error was set
2743 *
2744 * Since: 2.4
2745 **/
2746 gboolean
gdk_pixbuf_save_to_buffer(GdkPixbuf * pixbuf,gchar ** buffer,gsize * buffer_size,const char * type,GError ** error,...)2747 gdk_pixbuf_save_to_buffer (GdkPixbuf *pixbuf,
2748 gchar **buffer,
2749 gsize *buffer_size,
2750 const char *type,
2751 GError **error,
2752 ...)
2753 {
2754 gchar **keys = NULL;
2755 gchar **values = NULL;
2756 va_list args;
2757 gboolean result;
2758
2759 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2760
2761 va_start (args, error);
2762
2763 collect_save_options (args, &keys, &values);
2764
2765 va_end (args);
2766
2767 result = gdk_pixbuf_save_to_bufferv (pixbuf, buffer, buffer_size,
2768 type, keys, values,
2769 error);
2770
2771 g_strfreev (keys);
2772 g_strfreev (values);
2773
2774 return result;
2775 }
2776
2777 struct SaveToBufferData {
2778 gchar *buffer;
2779 gsize len, max;
2780 };
2781
2782 static gboolean
save_to_buffer_callback(const gchar * data,gsize count,GError ** error,gpointer user_data)2783 save_to_buffer_callback (const gchar *data,
2784 gsize count,
2785 GError **error,
2786 gpointer user_data)
2787 {
2788 struct SaveToBufferData *sdata = user_data;
2789 gchar *new_buffer;
2790 gsize new_max;
2791
2792 if (sdata->len + count > sdata->max) {
2793 new_max = MAX (sdata->max*2, sdata->len + count);
2794 new_buffer = g_try_realloc (sdata->buffer, new_max);
2795 if (!new_buffer) {
2796 g_set_error_literal (error,
2797 GDK_PIXBUF_ERROR,
2798 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2799 _("Insufficient memory to save image into a buffer"));
2800 return FALSE;
2801 }
2802 sdata->buffer = new_buffer;
2803 sdata->max = new_max;
2804 }
2805 memcpy (sdata->buffer + sdata->len, data, count);
2806 sdata->len += count;
2807 return TRUE;
2808 }
2809
2810 /**
2811 * gdk_pixbuf_save_to_bufferv:
2812 * @pixbuf: a #GdkPixbuf.
2813 * @buffer: (array length=buffer_size) (out) (element-type guint8):
2814 * location to receive a pointer to the new buffer.
2815 * @buffer_size: location to receive the size of the new buffer.
2816 * @type: name of file format.
2817 * @option_keys: (array zero-terminated=1): name of options to set, %NULL-terminated
2818 * @option_values: (array zero-terminated=1): values for named options
2819 * @error: (allow-none): return location for error, or %NULL
2820 *
2821 * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
2822 * "tiff", "png", "ico" or "bmp". See gdk_pixbuf_save_to_buffer()
2823 * for more details.
2824 *
2825 * Return value: whether an error was set
2826 *
2827 * Since: 2.4
2828 **/
2829 gboolean
gdk_pixbuf_save_to_bufferv(GdkPixbuf * pixbuf,gchar ** buffer,gsize * buffer_size,const char * type,char ** option_keys,char ** option_values,GError ** error)2830 gdk_pixbuf_save_to_bufferv (GdkPixbuf *pixbuf,
2831 gchar **buffer,
2832 gsize *buffer_size,
2833 const char *type,
2834 char **option_keys,
2835 char **option_values,
2836 GError **error)
2837 {
2838 static const gint initial_max = 1024;
2839 struct SaveToBufferData sdata;
2840
2841 *buffer = NULL;
2842 *buffer_size = 0;
2843
2844 sdata.buffer = g_try_malloc (initial_max);
2845 sdata.max = initial_max;
2846 sdata.len = 0;
2847 if (!sdata.buffer) {
2848 g_set_error_literal (error,
2849 GDK_PIXBUF_ERROR,
2850 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2851 _("Insufficient memory to save image into a buffer"));
2852 return FALSE;
2853 }
2854
2855 if (!gdk_pixbuf_save_to_callbackv (pixbuf,
2856 save_to_buffer_callback, &sdata,
2857 type, option_keys, option_values,
2858 error)) {
2859 g_free (sdata.buffer);
2860 return FALSE;
2861 }
2862
2863 *buffer = sdata.buffer;
2864 *buffer_size = sdata.len;
2865 return TRUE;
2866 }
2867
2868 typedef struct {
2869 GOutputStream *stream;
2870 GCancellable *cancellable;
2871 } SaveToStreamData;
2872
2873 static gboolean
save_to_stream(const gchar * buffer,gsize count,GError ** error,gpointer data)2874 save_to_stream (const gchar *buffer,
2875 gsize count,
2876 GError **error,
2877 gpointer data)
2878 {
2879 SaveToStreamData *sdata = (SaveToStreamData *)data;
2880 gsize remaining;
2881 gssize written;
2882 GError *my_error = NULL;
2883
2884 remaining = count;
2885 written = 0;
2886 while (remaining > 0) {
2887 buffer += written;
2888 remaining -= written;
2889 written = g_output_stream_write (sdata->stream,
2890 buffer, remaining,
2891 sdata->cancellable,
2892 &my_error);
2893 if (written < 0) {
2894 if (!my_error) {
2895 g_set_error_literal (error,
2896 G_IO_ERROR, 0,
2897 _("Error writing to image stream"));
2898 }
2899 else {
2900 g_propagate_error (error, my_error);
2901 }
2902 return FALSE;
2903 }
2904 }
2905
2906 return TRUE;
2907 }
2908
2909 /**
2910 * gdk_pixbuf_save_to_streamv:
2911 * @pixbuf: a #GdkPixbuf
2912 * @stream: a #GOutputStream to save the pixbuf to
2913 * @type: name of file format
2914 * @option_keys: (array zero-terminated=1): name of options to set, %NULL-terminated
2915 * @option_values: (array zero-terminated=1): values for named options
2916 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
2917 * @error: (allow-none): return location for error, or %NULL
2918 *
2919 * Saves @pixbuf to an output stream.
2920 *
2921 * Supported file formats are currently "jpeg", "tiff", "png", "ico" or
2922 * "bmp". See gdk_pixbuf_save_to_stream() for more details.
2923 *
2924 * Returns: %TRUE if the pixbuf was saved successfully, %FALSE if an
2925 * error was set.
2926 *
2927 * Since: 2.36
2928 */
2929 gboolean
gdk_pixbuf_save_to_streamv(GdkPixbuf * pixbuf,GOutputStream * stream,const char * type,char ** option_keys,char ** option_values,GCancellable * cancellable,GError ** error)2930 gdk_pixbuf_save_to_streamv (GdkPixbuf *pixbuf,
2931 GOutputStream *stream,
2932 const char *type,
2933 char **option_keys,
2934 char **option_values,
2935 GCancellable *cancellable,
2936 GError **error)
2937 {
2938 SaveToStreamData data;
2939
2940 data.stream = stream;
2941 data.cancellable = cancellable;
2942
2943 return gdk_pixbuf_save_to_callbackv (pixbuf, save_to_stream,
2944 &data, type,
2945 option_keys, option_values,
2946 error);
2947 }
2948
2949 /**
2950 * gdk_pixbuf_save_to_stream:
2951 * @pixbuf: a #GdkPixbuf
2952 * @stream: a #GOutputStream to save the pixbuf to
2953 * @type: name of file format
2954 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
2955 * @error: (allow-none): return location for error, or %NULL
2956 * @...: list of key-value save options
2957 *
2958 * Saves @pixbuf to an output stream.
2959 *
2960 * Supported file formats are currently "jpeg", "tiff", "png", "ico" or
2961 * "bmp". See gdk_pixbuf_save_to_buffer() for more details.
2962 *
2963 * The @cancellable can be used to abort the operation from another
2964 * thread. If the operation was cancelled, the error %G_IO_ERROR_CANCELLED
2965 * will be returned. Other possible errors are in the #GDK_PIXBUF_ERROR
2966 * and %G_IO_ERROR domains.
2967 *
2968 * The stream is not closed.
2969 *
2970 * Returns: %TRUE if the pixbuf was saved successfully, %FALSE if an
2971 * error was set.
2972 *
2973 * Since: 2.14
2974 */
2975 gboolean
gdk_pixbuf_save_to_stream(GdkPixbuf * pixbuf,GOutputStream * stream,const char * type,GCancellable * cancellable,GError ** error,...)2976 gdk_pixbuf_save_to_stream (GdkPixbuf *pixbuf,
2977 GOutputStream *stream,
2978 const char *type,
2979 GCancellable *cancellable,
2980 GError **error,
2981 ...)
2982 {
2983 gboolean res;
2984 gchar **keys = NULL;
2985 gchar **values = NULL;
2986 va_list args;
2987
2988 va_start (args, error);
2989 collect_save_options (args, &keys, &values);
2990 va_end (args);
2991
2992 res = gdk_pixbuf_save_to_streamv (pixbuf, stream, type,
2993 keys, values,
2994 cancellable, error);
2995
2996 g_strfreev (keys);
2997 g_strfreev (values);
2998
2999 return res;
3000 }
3001
3002 typedef struct {
3003 GOutputStream *stream;
3004 gchar *type;
3005 gchar **keys;
3006 gchar **values;
3007 } SaveToStreamAsyncData;
3008
3009 static void
save_to_stream_async_data_free(SaveToStreamAsyncData * data)3010 save_to_stream_async_data_free (SaveToStreamAsyncData *data)
3011 {
3012 if (data->stream)
3013 g_object_unref (data->stream);
3014 g_strfreev (data->keys);
3015 g_strfreev (data->values);
3016 g_free (data->type);
3017 g_slice_free (SaveToStreamAsyncData, data);
3018 }
3019
3020 static void
save_to_stream_thread(GTask * task,GdkPixbuf * pixbuf,SaveToStreamAsyncData * data,GCancellable * cancellable)3021 save_to_stream_thread (GTask *task,
3022 GdkPixbuf *pixbuf,
3023 SaveToStreamAsyncData *data,
3024 GCancellable *cancellable)
3025 {
3026 SaveToStreamData sync_data;
3027 gboolean retval;
3028 GError *error = NULL;
3029
3030 sync_data.stream = data->stream;
3031 sync_data.cancellable = cancellable;
3032
3033 retval = gdk_pixbuf_save_to_callbackv (pixbuf, save_to_stream,
3034 &sync_data, data->type,
3035 data->keys, data->values,
3036 &error);
3037
3038 if (retval == FALSE) {
3039 g_task_return_error (task, error);
3040 } else {
3041 g_task_return_boolean (task, TRUE);
3042 }
3043 }
3044
3045 /**
3046 * gdk_pixbuf_save_to_streamv_async:
3047 * @pixbuf: a #GdkPixbuf
3048 * @stream: a #GOutputStream to which to save the pixbuf
3049 * @type: name of file format
3050 * @option_keys: (array zero-terminated=1): name of options to set, %NULL-terminated
3051 * @option_values: (array zero-terminated=1): values for named options
3052 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
3053 * @callback: a #GAsyncReadyCallback to call when the pixbuf is saved
3054 * @user_data: the data to pass to the callback function
3055 *
3056 * Saves @pixbuf to an output stream asynchronously.
3057 *
3058 * For more details see gdk_pixbuf_save_to_streamv(), which is the synchronous
3059 * version of this function.
3060 *
3061 * When the operation is finished, @callback will be called in the main thread.
3062 * You can then call gdk_pixbuf_save_to_stream_finish() to get the result of the operation.
3063 *
3064 * Since: 2.36
3065 **/
3066 void
gdk_pixbuf_save_to_streamv_async(GdkPixbuf * pixbuf,GOutputStream * stream,const gchar * type,gchar ** option_keys,gchar ** option_values,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)3067 gdk_pixbuf_save_to_streamv_async (GdkPixbuf *pixbuf,
3068 GOutputStream *stream,
3069 const gchar *type,
3070 gchar **option_keys,
3071 gchar **option_values,
3072 GCancellable *cancellable,
3073 GAsyncReadyCallback callback,
3074 gpointer user_data)
3075 {
3076 GTask *task;
3077 SaveToStreamAsyncData *data;
3078
3079 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3080 g_return_if_fail (gdk_pixbuf_get_width (pixbuf) >= 0);
3081 g_return_if_fail (gdk_pixbuf_get_height (pixbuf) >= 0);
3082 g_return_if_fail (gdk_pixbuf_get_n_channels (pixbuf) >= 0);
3083 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
3084 g_return_if_fail (type != NULL);
3085 g_return_if_fail (callback != NULL);
3086 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
3087
3088 data = g_slice_new (SaveToStreamAsyncData);
3089 data->stream = g_object_ref (stream);
3090 data->type = g_strdup (type);
3091 data->keys = g_strdupv (option_keys);
3092 data->values = g_strdupv (option_values);
3093
3094 task = g_task_new (pixbuf, cancellable, callback, user_data);
3095 g_task_set_source_tag (task, gdk_pixbuf_save_to_streamv_async);
3096 g_task_set_task_data (task, data, (GDestroyNotify) save_to_stream_async_data_free);
3097 g_task_run_in_thread (task, (GTaskThreadFunc) save_to_stream_thread);
3098 g_object_unref (task);
3099 }
3100
3101 /**
3102 * gdk_pixbuf_save_to_stream_async:
3103 * @pixbuf: a #GdkPixbuf
3104 * @stream: a #GOutputStream to which to save the pixbuf
3105 * @type: name of file format
3106 * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
3107 * @callback: a #GAsyncReadyCallback to call when the pixbuf is saved
3108 * @user_data: the data to pass to the callback function
3109 * @...: list of key-value save options
3110 *
3111 * Saves @pixbuf to an output stream asynchronously.
3112 *
3113 * For more details see gdk_pixbuf_save_to_stream(), which is the synchronous
3114 * version of this function.
3115 *
3116 * When the operation is finished, @callback will be called in the main thread.
3117 * You can then call gdk_pixbuf_save_to_stream_finish() to get the result of the operation.
3118 *
3119 * Since: 2.24
3120 **/
3121 void
gdk_pixbuf_save_to_stream_async(GdkPixbuf * pixbuf,GOutputStream * stream,const gchar * type,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,...)3122 gdk_pixbuf_save_to_stream_async (GdkPixbuf *pixbuf,
3123 GOutputStream *stream,
3124 const gchar *type,
3125 GCancellable *cancellable,
3126 GAsyncReadyCallback callback,
3127 gpointer user_data,
3128 ...)
3129 {
3130 gchar **keys = NULL;
3131 gchar **values = NULL;
3132 va_list args;
3133
3134 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3135 g_return_if_fail (gdk_pixbuf_get_width (pixbuf) >= 0);
3136 g_return_if_fail (gdk_pixbuf_get_height (pixbuf) >= 0);
3137 g_return_if_fail (gdk_pixbuf_get_n_channels (pixbuf) >= 0);
3138 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
3139 g_return_if_fail (type != NULL);
3140 g_return_if_fail (callback != NULL);
3141 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
3142
3143 va_start (args, user_data);
3144 collect_save_options (args, &keys, &values);
3145 va_end (args);
3146
3147 gdk_pixbuf_save_to_streamv_async (pixbuf, stream, type,
3148 keys, values,
3149 cancellable, callback, user_data);
3150 g_strfreev (keys);
3151 g_strfreev (values);
3152 }
3153
3154 /**
3155 * gdk_pixbuf_save_to_stream_finish:
3156 * @async_result: a #GAsyncResult
3157 * @error: a #GError, or %NULL
3158 *
3159 * Finishes an asynchronous pixbuf save operation started with
3160 * gdk_pixbuf_save_to_stream_async().
3161 *
3162 * Return value: %TRUE if the pixbuf was saved successfully, %FALSE if an error was set.
3163 *
3164 * Since: 2.24
3165 **/
3166 gboolean
gdk_pixbuf_save_to_stream_finish(GAsyncResult * async_result,GError ** error)3167 gdk_pixbuf_save_to_stream_finish (GAsyncResult *async_result,
3168 GError **error)
3169 {
3170 GTask *task;
3171
3172 /* Can not use g_task_is_valid because our GTask has a
3173 * source_object which is not available to us anymore.
3174 */
3175 g_return_val_if_fail (G_IS_TASK (async_result), FALSE);
3176
3177 task = G_TASK (async_result);
3178
3179 g_return_val_if_fail (!error || (error && !*error), FALSE);
3180 g_warn_if_fail (g_task_get_source_tag (task) == gdk_pixbuf_save_to_stream_async ||
3181 g_task_get_source_tag (task) == gdk_pixbuf_save_to_streamv_async);
3182
3183 return g_task_propagate_boolean (task, error);
3184 }
3185
3186 /**
3187 * gdk_pixbuf_format_get_name:
3188 * @format: a #GdkPixbufFormat
3189 *
3190 * Returns the name of the format.
3191 *
3192 * Return value: the name of the format.
3193 *
3194 * Since: 2.2
3195 */
3196 gchar *
gdk_pixbuf_format_get_name(GdkPixbufFormat * format)3197 gdk_pixbuf_format_get_name (GdkPixbufFormat *format)
3198 {
3199 g_return_val_if_fail (format != NULL, NULL);
3200
3201 return g_strdup (format->name);
3202 }
3203
3204 /**
3205 * gdk_pixbuf_format_get_description:
3206 * @format: a #GdkPixbufFormat
3207 *
3208 * Returns a description of the format.
3209 *
3210 * Return value: a description of the format.
3211 *
3212 * Since: 2.2
3213 */
3214 gchar *
gdk_pixbuf_format_get_description(GdkPixbufFormat * format)3215 gdk_pixbuf_format_get_description (GdkPixbufFormat *format)
3216 {
3217 gchar *domain;
3218 const gchar *description;
3219 g_return_val_if_fail (format != NULL, NULL);
3220
3221 if (format->domain != NULL)
3222 domain = format->domain;
3223 else
3224 domain = GETTEXT_PACKAGE;
3225 description = g_dgettext (domain, format->description);
3226
3227 return g_strdup (description);
3228 }
3229
3230 /**
3231 * gdk_pixbuf_format_get_mime_types:
3232 * @format: a #GdkPixbufFormat
3233 *
3234 * Returns the mime types supported by the format.
3235 *
3236 * Return value: (transfer full): a %NULL-terminated array of mime types which must be freed with
3237 * g_strfreev() when it is no longer needed.
3238 *
3239 * Since: 2.2
3240 */
3241 gchar **
gdk_pixbuf_format_get_mime_types(GdkPixbufFormat * format)3242 gdk_pixbuf_format_get_mime_types (GdkPixbufFormat *format)
3243 {
3244 g_return_val_if_fail (format != NULL, NULL);
3245
3246 return g_strdupv (format->mime_types);
3247 }
3248
3249 /**
3250 * gdk_pixbuf_format_get_extensions:
3251 * @format: a #GdkPixbufFormat
3252 *
3253 * Returns the filename extensions typically used for files in the
3254 * given format.
3255 *
3256 * Return value: (transfer full): a %NULL-terminated array of filename extensions which must be
3257 * freed with g_strfreev() when it is no longer needed.
3258 *
3259 * Since: 2.2
3260 */
3261 gchar **
gdk_pixbuf_format_get_extensions(GdkPixbufFormat * format)3262 gdk_pixbuf_format_get_extensions (GdkPixbufFormat *format)
3263 {
3264 g_return_val_if_fail (format != NULL, NULL);
3265
3266 return g_strdupv (format->extensions);
3267 }
3268
3269 /**
3270 * gdk_pixbuf_format_is_writable:
3271 * @format: a #GdkPixbufFormat
3272 *
3273 * Returns whether pixbufs can be saved in the given format.
3274 *
3275 * Return value: whether pixbufs can be saved in the given format.
3276 *
3277 * Since: 2.2
3278 */
3279 gboolean
gdk_pixbuf_format_is_writable(GdkPixbufFormat * format)3280 gdk_pixbuf_format_is_writable (GdkPixbufFormat *format)
3281 {
3282 g_return_val_if_fail (format != NULL, FALSE);
3283
3284 return (format->flags & GDK_PIXBUF_FORMAT_WRITABLE) != 0;
3285 }
3286
3287 /**
3288 * gdk_pixbuf_format_is_scalable:
3289 * @format: a #GdkPixbufFormat
3290 *
3291 * Returns whether this image format is scalable. If a file is in a
3292 * scalable format, it is preferable to load it at the desired size,
3293 * rather than loading it at the default size and scaling the
3294 * resulting pixbuf to the desired size.
3295 *
3296 * Return value: whether this image format is scalable.
3297 *
3298 * Since: 2.6
3299 */
3300 gboolean
gdk_pixbuf_format_is_scalable(GdkPixbufFormat * format)3301 gdk_pixbuf_format_is_scalable (GdkPixbufFormat *format)
3302 {
3303 g_return_val_if_fail (format != NULL, FALSE);
3304
3305 return (format->flags & GDK_PIXBUF_FORMAT_SCALABLE) != 0;
3306 }
3307
3308 /**
3309 * gdk_pixbuf_format_is_disabled:
3310 * @format: a #GdkPixbufFormat
3311 *
3312 * Returns whether this image format is disabled. See
3313 * gdk_pixbuf_format_set_disabled().
3314 *
3315 * Return value: whether this image format is disabled.
3316 *
3317 * Since: 2.6
3318 */
3319 gboolean
gdk_pixbuf_format_is_disabled(GdkPixbufFormat * format)3320 gdk_pixbuf_format_is_disabled (GdkPixbufFormat *format)
3321 {
3322 g_return_val_if_fail (format != NULL, FALSE);
3323
3324 return format->disabled;
3325 }
3326
3327 /**
3328 * gdk_pixbuf_format_set_disabled:
3329 * @format: a #GdkPixbufFormat
3330 * @disabled: %TRUE to disable the format @format
3331 *
3332 * Disables or enables an image format. If a format is disabled,
3333 * gdk-pixbuf won't use the image loader for this format to load
3334 * images. Applications can use this to avoid using image loaders
3335 * with an inappropriate license, see gdk_pixbuf_format_get_license().
3336 *
3337 * Since: 2.6
3338 */
3339 void
gdk_pixbuf_format_set_disabled(GdkPixbufFormat * format,gboolean disabled)3340 gdk_pixbuf_format_set_disabled (GdkPixbufFormat *format,
3341 gboolean disabled)
3342 {
3343 g_return_if_fail (format != NULL);
3344
3345 format->disabled = disabled != FALSE;
3346 }
3347
3348 /**
3349 * gdk_pixbuf_format_get_license:
3350 * @format: a #GdkPixbufFormat
3351 *
3352 * Returns information about the license of the image loader for the format. The
3353 * returned string should be a shorthand for a wellknown license, e.g. "LGPL",
3354 * "GPL", "QPL", "GPL/QPL", or "other" to indicate some other license. This
3355 * string should be freed with g_free() when it's no longer needed.
3356 *
3357 * Returns: a string describing the license of @format.
3358 *
3359 * Since: 2.6
3360 */
3361 gchar*
gdk_pixbuf_format_get_license(GdkPixbufFormat * format)3362 gdk_pixbuf_format_get_license (GdkPixbufFormat *format)
3363 {
3364 g_return_val_if_fail (format != NULL, NULL);
3365
3366 return g_strdup (format->license);
3367 }
3368
3369 GdkPixbufFormat *
_gdk_pixbuf_get_format(GdkPixbufModule * module)3370 _gdk_pixbuf_get_format (GdkPixbufModule *module)
3371 {
3372 g_return_val_if_fail (module != NULL, NULL);
3373
3374 return module->info;
3375 }
3376
3377 /**
3378 * gdk_pixbuf_get_formats:
3379 *
3380 * Obtains the available information about the image formats supported
3381 * by GdkPixbuf.
3382 *
3383 * Returns: (transfer container) (element-type GdkPixbufFormat): A list of
3384 * #GdkPixbufFormats describing the supported image formats. The list should
3385 * be freed when it is no longer needed, but the structures themselves are
3386 * owned by #GdkPixbuf and should not be freed.
3387 *
3388 * Since: 2.2
3389 */
3390 GSList *
gdk_pixbuf_get_formats(void)3391 gdk_pixbuf_get_formats (void)
3392 {
3393 GSList *result = NULL;
3394 GSList *modules;
3395
3396 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
3397 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
3398 GdkPixbufFormat *info = _gdk_pixbuf_get_format (module);
3399 result = g_slist_prepend (result, info);
3400 }
3401
3402 return result;
3403 }
3404
3405 /**
3406 * gdk_pixbuf_format_copy:
3407 * @format: a #GdkPixbufFormat
3408 *
3409 * Creates a copy of @format
3410 *
3411 * Return value: the newly allocated copy of a #GdkPixbufFormat. Use
3412 * gdk_pixbuf_format_free() to free the resources when done
3413 *
3414 * Since: 2.22
3415 */
3416 GdkPixbufFormat *
gdk_pixbuf_format_copy(const GdkPixbufFormat * format)3417 gdk_pixbuf_format_copy (const GdkPixbufFormat *format)
3418 {
3419 if (G_LIKELY (format != NULL))
3420 return g_slice_dup (GdkPixbufFormat, format);
3421
3422 return NULL;
3423 }
3424
3425 /**
3426 * gdk_pixbuf_format_free:
3427 * @format: a #GdkPixbufFormat
3428 *
3429 * Frees the resources allocated when copying a #GdkPixbufFormat
3430 * using gdk_pixbuf_format_copy()
3431 *
3432 * Since: 2.22
3433 */
3434 void
gdk_pixbuf_format_free(GdkPixbufFormat * format)3435 gdk_pixbuf_format_free (GdkPixbufFormat *format)
3436 {
3437 if (G_LIKELY (format != NULL))
3438 g_slice_free (GdkPixbufFormat, format);
3439 }
3440
3441 /**
3442 * gdk_pixbuf_format_is_save_option_supported:
3443 * @format: a #GdkPixbufFormat
3444 * @option_key: the name of an option
3445 *
3446 * Returns %TRUE if the save option specified by @option_key is supported when
3447 * saving a pixbuf using the module implementing @format.
3448 * See gdk_pixbuf_save() for more information about option keys.
3449 *
3450 * Returns: %TRUE if the specified option is supported
3451 *
3452 * Since: 2.36
3453 */
3454 gboolean
gdk_pixbuf_format_is_save_option_supported(GdkPixbufFormat * format,const gchar * option_key)3455 gdk_pixbuf_format_is_save_option_supported (GdkPixbufFormat *format,
3456 const gchar *option_key)
3457 {
3458 GdkPixbufModule *module;
3459
3460 g_return_val_if_fail (format != NULL, FALSE);
3461 g_return_val_if_fail (option_key != NULL, FALSE);
3462
3463 module = _gdk_pixbuf_get_named_module (format->name, NULL);
3464 if (!module)
3465 return FALSE;
3466
3467 if (!_gdk_pixbuf_load_module (module, NULL))
3468 return FALSE;
3469
3470 if (!module->is_save_option_supported)
3471 return FALSE;
3472
3473 return (* module->is_save_option_supported) (option_key);
3474 }
3475
3476 G_DEFINE_BOXED_TYPE (GdkPixbufFormat, gdk_pixbuf_format,
3477 gdk_pixbuf_format_copy,
3478 gdk_pixbuf_format_free)
3479