1 /* -*- mode: C; c-file-style: "linux" -*- */
2 /* GdkPixbuf library - Main loading interface.
4 * Copyright (C) 1999 The Free Software Foundation
6 * Authors: Miguel de Icaza <miguel@gnu.org>
7 * Federico Mena-Quintero <federico@gimp.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
31 #include "gdk-pixbuf-private.h"
32 #include "gdk-pixbuf-io.h"
41 format_check (GdkPixbufModule *module, guchar *buffer, int size)
45 GdkPixbufModulePattern *pattern;
47 for (pattern = module->info->signature; pattern->prefix; pattern++) {
48 for (j = 0; j < size && pattern->prefix[j] != 0; j++) {
49 m = pattern->mask ? pattern->mask[j] : ' ';
51 if (buffer[j] != pattern->prefix[j])
55 if (buffer[j] == pattern->prefix[j])
67 if (pattern->prefix[j] == 0)
68 return pattern->relevance;
73 static GSList *file_formats = NULL;
75 static void gdk_pixbuf_io_init ();
80 if (file_formats == NULL)
81 gdk_pixbuf_io_init ();
90 scan_string (const char **pos, GString *out)
92 const char *p = *pos, *q = *pos;
96 while (g_ascii_isspace (*p))
101 else if (*p == '"') {
104 for (q = p; (*q != '"') || quoted; q++) {
107 quoted = (*q == '\\') && !quoted;
110 tmp = g_strndup (p, q - p);
111 tmp2 = g_strcompress (tmp);
112 g_string_truncate (out, 0);
113 g_string_append (out, tmp2);
125 scan_int (const char **pos, int *out)
129 const char *p = *pos;
131 while (g_ascii_isspace (*p))
134 if (*p < '0' || *p > '9')
137 while ((*p >= '0') && (*p <= '9') && i < sizeof (buf)) {
143 if (i == sizeof (buf))
156 skip_space (const char **pos)
158 const char *p = *pos;
160 while (g_ascii_isspace (*p))
165 return !(*p == '\0');
169 gdk_pixbuf_get_module_file (void)
171 gchar *result = g_strdup (g_getenv ("GDK_PIXBUF_MODULE_FILE"));
174 result = g_build_filename (GTK_SYSCONFDIR, "gtk-2.0", "gdk-pixbuf.loaders", NULL);
180 gdk_pixbuf_io_init ()
185 GString *tmp_buf = g_string_new (NULL);
186 gboolean have_error = FALSE;
187 GdkPixbufModule *module = NULL;
188 gchar *filename = gdk_pixbuf_get_module_file ();
191 GdkPixbufModulePattern *pattern;
192 GError *error = NULL;
194 channel = g_io_channel_new_file (filename, "r", &error);
196 g_warning ("Can not open pixbuf loader module file '%s': %s",
197 filename, error->message);
201 while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL, &term, NULL) == G_IO_STATUS_NORMAL) {
208 if (!skip_space (&p)) {
209 /* Blank line marking the end of a module
211 if (module && *p != '#') {
212 file_formats = g_slist_prepend (file_formats, module);
223 /* Read a module location
225 module = g_new0 (GdkPixbufModule, 1);
228 if (!scan_string (&p, tmp_buf)) {
229 g_warning ("Error parsing loader info in '%s'\n %s",
233 module->module_path = g_strdup (tmp_buf->str);
235 else if (!module->module_name) {
236 module->info = g_new0 (GdkPixbufFormat, 1);
237 if (!scan_string (&p, tmp_buf)) {
238 g_warning ("Error parsing loader info in '%s'\n %s",
242 module->info->name = g_strdup (tmp_buf->str);
243 module->module_name = module->info->name;
245 if (!scan_int (&p, &flags)) {
246 g_warning ("Error parsing loader info in '%s'\n %s",
250 module->info->flags = flags;
252 if (!scan_string (&p, tmp_buf)) {
253 g_warning ("Error parsing loader info in '%s'\n %s",
257 if (tmp_buf->str[0] != 0)
258 module->info->domain = g_strdup (tmp_buf->str);
260 if (!scan_string (&p, tmp_buf)) {
261 g_warning ("Error parsing loader info in '%s'\n %s",
265 module->info->description = g_strdup (tmp_buf->str);
267 else if (!module->info->mime_types) {
269 module->info->mime_types = g_new0 (gchar*, 1);
270 while (scan_string (&p, tmp_buf)) {
271 if (tmp_buf->str[0] != 0) {
272 module->info->mime_types =
273 g_realloc (module->info->mime_types, (n + 1) * sizeof (gchar*));
274 module->info->mime_types[n - 1] = g_strdup (tmp_buf->str);
275 module->info->mime_types[n] = 0;
280 else if (!module->info->extensions) {
282 module->info->extensions = g_new0 (gchar*, 1);
283 while (scan_string (&p, tmp_buf)) {
284 if (tmp_buf->str[0] != 0) {
285 module->info->extensions =
286 g_realloc (module->info->extensions, (n + 1) * sizeof (gchar*));
287 module->info->extensions[n - 1] = g_strdup (tmp_buf->str);
288 module->info->extensions[n] = 0;
295 module->info->signature = (GdkPixbufModulePattern *)
296 g_realloc (module->info->signature, (n_patterns + 1) * sizeof (GdkPixbufModulePattern));
297 pattern = module->info->signature + n_patterns;
298 pattern->prefix = NULL;
299 pattern->mask = NULL;
300 pattern->relevance = 0;
302 if (!scan_string (&p, tmp_buf))
304 pattern->prefix = g_strdup (tmp_buf->str);
306 if (!scan_string (&p, tmp_buf))
309 pattern->mask = g_strdup (tmp_buf->str);
311 pattern->mask = NULL;
313 if (!scan_int (&p, &pattern->relevance))
319 g_free (pattern->prefix);
320 g_free (pattern->mask);
322 g_warning ("Error parsing loader info in '%s'\n %s",
329 g_string_free (tmp_buf, TRUE);
330 g_io_channel_unref (channel);
336 /* DllMain function needed to tuck away the gdk-pixbuf DLL name */
338 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
343 static char *libdir = NULL;
346 libdir = g_win32_get_package_installation_subdirectory
347 (GETTEXT_PACKAGE, dll_name, "lib\\gtk-2.0\\" GTK_BINARY_VERSION "\\loaders");
353 #define PIXBUF_LIBDIR get_libdir ()
357 /* actually load the image handler - gdk_pixbuf_get_module only get a */
358 /* reference to the module to load, it doesn't actually load it */
359 /* perhaps these actions should be combined in one function */
361 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
368 g_return_val_if_fail (image_module->module == NULL, FALSE);
370 path = image_module->module_path;
371 module = g_module_open (path, G_MODULE_BIND_LAZY);
376 GDK_PIXBUF_ERROR_FAILED,
377 _("Unable to load image-loading module: %s: %s"),
378 path, g_module_error ());
382 image_module->module = module;
384 if (g_module_symbol (module, "fill_vtable", &sym)) {
385 GdkPixbufModuleFillVtableFunc func = (GdkPixbufModuleFillVtableFunc) sym;
386 (* func) (image_module);
391 GDK_PIXBUF_ERROR_FAILED,
392 _("Image-loading module %s does not export the proper interface; perhaps it's from a different GTK version?"),
399 #define module(type) \
400 extern void MODULE_ENTRY (type, fill_info) (GdkPixbufFormat *info); \
401 extern void MODULE_ENTRY (type, fill_vtable) (GdkPixbufModule *module)
418 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
421 GdkPixbufModuleFillInfoFunc fill_info = NULL;
422 GdkPixbufModuleFillVtableFunc fill_vtable = NULL;
424 image_module->module = (void *) 1;
427 /* Ugly hack so we can use else if unconditionally below ;-) */
431 else if (strcmp (image_module->module_name, "png") == 0) {
432 fill_info = MODULE_ENTRY (png, fill_info);
433 fill_vtable = MODULE_ENTRY (png, fill_vtable);
438 else if (strcmp (image_module->module_name, "bmp") == 0) {
439 fill_info = MODULE_ENTRY (bmp, fill_info);
440 fill_vtable = MODULE_ENTRY (bmp, fill_vtable);
445 else if (strcmp (image_module->module_name, "wbmp") == 0) {
446 fill_info = MODULE_ENTRY (wbmp, fill_info);
447 fill_vtable = MODULE_ENTRY (wbmp, fill_vtable);
452 else if (strcmp (image_module->module_name, "gif") == 0) {
453 fill_info = MODULE_ENTRY (gif, fill_info);
454 fill_vtable = MODULE_ENTRY (gif, fill_vtable);
459 else if (strcmp (image_module->module_name, "ico") == 0) {
460 fill_info = MODULE_ENTRY (ico, fill_info);
461 fill_vtable = MODULE_ENTRY (ico, fill_vtable);
466 else if (strcmp (image_module->module_name, "ani") == 0) {
467 fill_info = MODULE_ENTRY (ani, fill_info);
468 fill_vtable = MODULE_ENTRY (ani, fill_vtable);
473 else if (strcmp (image_module->module_name, "jpeg") == 0) {
474 fill_info = MODULE_ENTRY (jpeg, fill_info);
475 fill_vtable = MODULE_ENTRY (jpeg, fill_vtable);
480 else if (strcmp (image_module->module_name, "pnm") == 0) {
481 fill_info = MODULE_ENTRY (pnm, fill_info);
482 fill_vtable = MODULE_ENTRY (pnm, fill_vtable);
487 else if (strcmp (image_module->module_name, "ras") == 0) {
488 fill_info = MODULE_ENTRY (ras, fill_info);
489 fill_vtable = MODULE_ENTRY (ras, fill_vtable);
494 else if (strcmp (image_module->module_name, "tiff") == 0) {
495 fill_info = MODULE_ENTRY (tiff, fill_info);
496 fill_vtable = MODULE_ENTRY (tiff, fill_vtable);
501 else if (strcmp (image_module->module_name, "xpm") == 0) {
502 fill_info = MODULE_ENTRY (xpm, fill_info);
503 fill_vtable = MODULE_ENTRY (xpm, fill_vtable);
508 else if (strcmp (image_module->module_name, "xbm") == 0) {
509 fill_info = MODULE_ENTRY (xbm, fill_info);
510 fill_vtable = MODULE_ENTRY (xbm, fill_vtable);
515 else if (strcmp (image_module->module_name, "tga") == 0) {
516 fill_info = MODULE_ENTRY (tga, fill_info);
517 fill_vtable = MODULE_ENTRY (tga, fill_vtable);
522 (* fill_vtable) (image_module);
523 image_module->info = g_new0 (GdkPixbufFormat, 1);
524 (* fill_info) (image_module->info);
530 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
531 _("Image type '%s' is not supported"),
532 image_module->module_name);
539 gdk_pixbuf_io_init ()
541 gchar *included_formats[] = {
542 "ani", "png", "bmp", "wbmp", "gif",
543 "ico", "jpeg", "pnm", "ras", "tiff",
548 GdkPixbufModule *module = NULL;
550 for (name = included_formats; *name; name++) {
551 module = g_new0 (GdkPixbufModule, 1);
552 module->module_name = *name;
553 if (_gdk_pixbuf_load_module (module, NULL))
554 file_formats = g_slist_prepend (file_formats, module);
565 _gdk_pixbuf_get_named_module (const char *name,
570 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
571 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
572 if (!strcmp (name, module->module_name))
578 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
579 _("Image type '%s' is not supported"),
586 _gdk_pixbuf_get_module (guchar *buffer, guint size,
587 const gchar *filename,
592 gint score, best = 0;
593 GdkPixbufModule *selected = NULL;
594 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
595 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
596 score = format_check (module, buffer, size);
604 if (selected != NULL)
610 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
611 _("Couldn't recognize the image file format for file '%s'"),
616 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
617 _("Unrecognized image file format"));
625 prepared_notify (GdkPixbuf *pixbuf,
626 GdkPixbufAnimation *anim,
630 g_object_ref (pixbuf);
631 *((GdkPixbuf **)user_data) = pixbuf;
635 _gdk_pixbuf_generic_image_load (GdkPixbufModule *module,
641 GdkPixbuf *pixbuf = NULL;
644 if (module->load != NULL)
645 return (* module->load) (f, error);
647 context = module->begin_load (NULL, prepared_notify, NULL, &pixbuf, error);
653 length = fread (buffer, 1, sizeof (buffer), f);
655 if (!module->load_increment (context, buffer, length, error)) {
656 module->stop_load (context, NULL);
658 g_object_unref (pixbuf);
663 if (!module->stop_load (context, error)) {
665 g_object_unref (pixbuf);
673 * gdk_pixbuf_new_from_file:
674 * @filename: Name of file to load.
675 * @error: Return location for an error
677 * Creates a new pixbuf by loading an image from a file. The file format is
678 * detected automatically. If %NULL is returned, then @error will be set.
679 * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
681 * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if
682 * any of several error conditions occurred: the file could not be opened,
683 * there was no loader for the file's format, there was not enough memory to
684 * allocate the image buffer, or the image file contained invalid data.
687 gdk_pixbuf_new_from_file (const char *filename,
694 GdkPixbufModule *image_module;
696 g_return_val_if_fail (filename != NULL, NULL);
698 f = fopen (filename, "rb");
702 g_file_error_from_errno (errno),
703 _("Failed to open file '%s': %s"),
704 filename, g_strerror (errno));
708 size = fread (&buffer, 1, sizeof (buffer), f);
712 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
713 _("Image file '%s' contains no data"),
720 image_module = _gdk_pixbuf_get_module (buffer, size, filename, error);
721 if (image_module == NULL) {
726 if (image_module->module == NULL)
727 if (!_gdk_pixbuf_load_module (image_module, error)) {
732 fseek (f, 0, SEEK_SET);
733 pixbuf = _gdk_pixbuf_generic_image_load (image_module, f, error);
736 if (pixbuf == NULL && error != NULL && *error == NULL) {
737 /* I don't trust these crufty longjmp()'ing image libs
738 * to maintain proper error invariants, and I don't
739 * want user code to segfault as a result. We need to maintain
740 * the invariastable/gdk-pixbuf/nt that error gets set if NULL is returned.
743 g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
746 GDK_PIXBUF_ERROR_FAILED,
747 _("Failed to load image '%s': reason not known, probably a corrupt image file"),
750 } else if (error != NULL && *error != NULL) {
752 /* Add the filename to the error message */
758 e->message = g_strdup_printf (_("Failed to load image '%s': %s"),
768 * gdk_pixbuf_new_from_xpm_data:
769 * @data: Pointer to inline XPM data.
771 * Creates a new pixbuf by parsing XPM data in memory. This data is commonly
772 * the result of including an XPM file into a program's C source.
774 * Return value: A newly-created pixbuf with a reference count of 1.
777 gdk_pixbuf_new_from_xpm_data (const char **data)
779 GdkPixbuf *(* load_xpm_data) (const char **data);
781 GError *error = NULL;
782 GdkPixbufModule *xpm_module = _gdk_pixbuf_get_named_module ("xpm", NULL);
784 if (xpm_module->module == NULL) {
785 if (!_gdk_pixbuf_load_module (xpm_module, &error)) {
786 g_warning ("Error loading XPM image loader: %s", error->message);
787 g_error_free (error);
792 if (xpm_module->module == NULL) {
793 g_warning ("Can't find gdk-pixbuf module for parsing inline XPM data");
795 } else if (xpm_module->load_xpm_data == NULL) {
796 g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
799 load_xpm_data = xpm_module->load_xpm_data;
801 pixbuf = (* load_xpm_data) (data);
806 collect_save_options (va_list opts,
819 next = va_arg (opts, gchar*);
823 val = va_arg (opts, gchar*);
828 *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
829 *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
831 (*keys)[count-1] = g_strdup (key);
832 (*vals)[count-1] = g_strdup (val);
834 (*keys)[count] = NULL;
835 (*vals)[count] = NULL;
837 next = va_arg (opts, gchar*);
842 gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
849 GdkPixbufModule *image_module = NULL;
851 image_module = _gdk_pixbuf_get_named_module (type, error);
853 if (image_module == NULL)
856 if (image_module->module == NULL)
857 if (!_gdk_pixbuf_load_module (image_module, error))
860 if (image_module->save == NULL) {
863 GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
864 _("This build of gdk-pixbuf does not support saving the image format: %s"),
869 return (* image_module->save) (filehandle, pixbuf,
877 * @pixbuf: a #GdkPixbuf.
878 * @filename: name of file to save.
879 * @type: name of file format.
880 * @error: return location for error, or %NULL
881 * @Varargs: list of key-value save options
883 * Saves pixbuf to a file in @type, which is currently "jpeg" or
884 * "png". If @error is set, %FALSE will be returned. Possible errors include
885 * those in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
887 * The variable argument list should be %NULL-terminated; if not empty,
888 * it should contain pairs of strings that modify the save
889 * parameters. For example:
890 * <informalexample><programlisting>
891 * gdk_pixbuf_save (pixbuf, handle, "jpeg", &error,
892 * "quality", "100", NULL);
893 * </programlisting></informalexample>
895 * Currently only few parameters exist. JPEG images can be saved with a
896 * "quality" parameter; its value should be in the range [0,100].
897 * Text chunks can be attached to PNG images by specifying parameters of
898 * the form "tEXt::key", where key is an ASCII string of length 1-79.
899 * The values are UTF-8 encoded strings.
901 * Return value: whether an error was set
905 gdk_pixbuf_save (GdkPixbuf *pixbuf,
906 const char *filename,
912 gchar **values = NULL;
916 va_start (args, error);
918 collect_save_options (args, &keys, &values);
922 result = gdk_pixbuf_savev (pixbuf, filename, type,
934 * @pixbuf: a #GdkPixbuf.
935 * @filename: name of file to save.
936 * @type: name of file format.
937 * @option_keys: name of options to set, %NULL-terminated
938 * @option_values: values for named options
939 * @error: return location for error, or %NULL
941 * Saves pixbuf to a file in @type, which is currently "jpeg" or "png".
942 * If @error is set, %FALSE will be returned. See gdk_pixbuf_save () for more
945 * Return value: whether an error was set
949 gdk_pixbuf_savev (GdkPixbuf *pixbuf,
950 const char *filename,
953 char **option_values,
960 g_return_val_if_fail (filename != NULL, FALSE);
961 g_return_val_if_fail (type != NULL, FALSE);
963 f = fopen (filename, "wb");
968 g_file_error_from_errno (errno),
969 _("Failed to open '%s' for writing: %s"),
970 filename, g_strerror (errno));
975 result = gdk_pixbuf_real_save (pixbuf, f, type,
976 option_keys, option_values,
981 g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
986 if (fclose (f) < 0) {
989 g_file_error_from_errno (errno),
990 _("Failed to close '%s' while writing image, all data may not have been saved: %s"),
991 filename, g_strerror (errno));
999 * gdk_pixbuf_format_get_name:
1000 * @format: a #GdkPixbufFormat
1002 * Returns the name of the format.
1004 * Return value: the name of the format.
1009 gdk_pixbuf_format_get_name (GdkPixbufFormat *format)
1011 g_return_val_if_fail (format != NULL, NULL);
1013 return g_strdup (format->name);
1017 * gdk_pixbuf_format_get_description:
1018 * @format: a #GdkPixbufFormat
1020 * Returns a description of the format.
1022 * Return value: a description of the format.
1027 gdk_pixbuf_format_get_description (GdkPixbufFormat *format)
1031 g_return_val_if_fail (format != NULL, NULL);
1033 if (format->domain != NULL)
1034 domain = format->domain;
1036 domain = GETTEXT_PACKAGE;
1037 description = dgettext (domain, format->description);
1039 return g_strdup (description);
1043 * gdk_pixbuf_format_get_mime_types:
1044 * @format: a #GdkPixbufFormat
1046 * Returns the mime types supported by the format.
1048 * Return value: a %NULL-terminated array of mime types.
1053 gdk_pixbuf_format_get_mime_types (GdkPixbufFormat *format)
1055 g_return_val_if_fail (format != NULL, NULL);
1057 return g_strdupv (format->mime_types);
1061 * gdk_pixbuf_format_get_extensions:
1062 * @format: a #GdkPixbufFormat
1064 * Returns the filename extensions typically used for files in the
1067 * Return value: a %NULL-terminated array of filename extensions.
1072 gdk_pixbuf_format_get_extensions (GdkPixbufFormat *format)
1074 g_return_val_if_fail (format != NULL, NULL);
1076 return g_strdupv (format->extensions);
1080 * gdk_pixbuf_format_is_writable:
1081 * @format: a #GdkPixbufFormat
1083 * Returns whether pixbufs can be saved in the given format.
1085 * Return value: whether pixbufs can be saved in the given format.
1090 gdk_pixbuf_format_is_writable (GdkPixbufFormat *format)
1092 g_return_val_if_fail (format != NULL, FALSE);
1094 return (format->flags & GDK_PIXBUF_FORMAT_WRITABLE) != 0;
1098 _gdk_pixbuf_get_format (GdkPixbufModule *module)
1100 g_return_val_if_fail (module != NULL, NULL);
1102 return module->info;
1106 * gdk_pixbuf_get_formats:
1108 * Obtains the available information about the image formats supported
1111 * Returns: A list of #GdkPixbufFormat<!-- -->s describing the supported
1112 * image formats. The list should be freed when it is no longer needed,
1113 * but the structures themselves are owned by #GdkPixbuf and should not be
1119 gdk_pixbuf_get_formats (void)
1121 GSList *result = NULL;
1124 for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
1125 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
1126 GdkPixbufFormat *info = _gdk_pixbuf_get_format (module);
1127 result = g_slist_prepend (result, info);