1 /* GdkPixbuf library - Main loading interface.
3 * Copyright (C) 1999 The Free Software Foundation
5 * Authors: Miguel de Icaza <miguel@gnu.org>
6 * Federico Mena-Quintero <federico@gimp.org>
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.
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.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
28 #include "gdk-pixbuf-private.h"
29 #include "gdk-pixbuf-io.h"
39 pixbuf_check_png (guchar *buffer, int size)
44 if (buffer [0] != 0x89 ||
58 pixbuf_check_jpeg (guchar *buffer, int size)
63 if (buffer [0] != 0xff || buffer [1] != 0xd8)
70 pixbuf_check_tiff (guchar *buffer, int size)
75 if (buffer [0] == 'M' &&
81 if (buffer [0] == 'I' &&
91 pixbuf_check_gif (guchar *buffer, int size)
96 if (strncmp (buffer, "GIF8", 4) == 0)
103 pixbuf_check_xpm (guchar *buffer, int size)
108 if (strncmp (buffer, "/* XPM */", 9) == 0)
115 pixbuf_check_pnm (guchar *buffer, int size)
120 if (buffer [0] == 'P') {
121 if (buffer [1] == '1' ||
132 pixbuf_check_sunras (guchar *buffer, int size)
137 if (buffer [0] != 0x59 ||
138 buffer [1] != 0xA6 ||
139 buffer [2] != 0x6A ||
147 pixbuf_check_ico (guchar *buffer, int size)
149 /* Note that this may cause false positives, but .ico's don't
150 have a magic number.*/
153 if (buffer [0] != 0x0 ||
155 ((buffer [2] != 0x1)&&(buffer[2]!=0x2)) ||
165 pixbuf_check_bmp (guchar *buffer, int size)
170 if (buffer [0] != 'B' || buffer [1] != 'M')
177 pixbuf_check_wbmp (guchar *buffer, int size)
179 if(size < 10) /* at least */
182 if(buffer[0] == '\0' /* We only handle type 0 wbmp's for now */)
188 static GdkPixbufModule file_formats [] = {
189 { "png", pixbuf_check_png, NULL, NULL, NULL, NULL, NULL, NULL, NULL, },
190 { "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
191 { "tiff", pixbuf_check_tiff, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
192 { "gif", pixbuf_check_gif, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
193 #define XPM_FILE_FORMAT_INDEX 4
194 { "xpm", pixbuf_check_xpm, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
195 { "pnm", pixbuf_check_pnm, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
196 { "ras", pixbuf_check_sunras, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
197 { "ico", pixbuf_check_ico, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
198 { "bmp", pixbuf_check_bmp, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
199 { "wbmp", pixbuf_check_wbmp, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
200 { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
205 pixbuf_module_symbol (GModule *module, const char *module_name, const char *symbol_name, gpointer *symbol)
207 char *full_symbol_name = g_strconcat ("gdk_pixbuf__", module_name, "_", symbol_name, NULL);
208 gboolean return_value;
210 return_value = g_module_symbol (module, full_symbol_name, symbol);
211 g_free (full_symbol_name);
218 /* What would be the right place for this function? Also
219 * gtk needs this function (to find the gtkrc and themes).
220 * But it seems stupid for the gdk-pixbuf DLL to depend
221 * on the gtk DLL. Should it be in the gdk DLL? Or should we
222 * have a small static library at the top gtk+ level?
226 gtk_win32_get_installation_directory (void)
228 static gboolean been_here = FALSE;
229 static gchar gtk_installation_dir[200];
233 DWORD nbytes = sizeof (gtk_installation_dir);
236 return gtk_installation_dir;
240 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\GNU\\GTk+", 0,
241 KEY_QUERY_VALUE, ®_key) != ERROR_SUCCESS
242 || RegQueryValueEx (reg_key, "InstallationDirectory", 0,
243 &type, gtk_installation_dir, &nbytes) != ERROR_SUCCESS
246 /* Uh oh. Use hard-coded %WinDir%\gtk+ value */
247 GetWindowsDirectory (win_dir, sizeof (win_dir));
248 sprintf (gtk_installation_dir, "%s\\gtk+", win_dir);
252 RegCloseKey (reg_key);
254 return gtk_installation_dir;
260 static char *libdir = NULL;
263 libdir = g_strdup_printf (gtk_win32_get_installation_directory (),
271 #define PIXBUF_LIBDIR get_libdir ()
275 /* actually load the image handler - gdk_pixbuf_get_module only get a */
276 /* reference to the module to load, it doesn't actually load it */
277 /* perhaps these actions should be combined in one function */
279 gdk_pixbuf_load_module (GdkPixbufModule *image_module,
289 g_return_val_if_fail (image_module->module == NULL, FALSE);
291 name = image_module->module_name;
293 module_name = g_strconcat ("pixbufloader-", name, NULL);
294 path = g_module_build_path (PIXBUF_LIBDIR, module_name);
296 module = g_module_open (path, G_MODULE_BIND_LAZY);
298 /* Debug feature, check in GDK_PIXBUF_MODULEDIR, or working directory */
299 char *dir = g_getenv ("GDK_PIXBUF_MODULEDIR");
304 path = g_module_build_path (dir, module_name);
305 module = g_module_open (path, G_MODULE_BIND_LAZY);
310 GDK_PIXBUF_ERROR_FAILED,
311 _("Unable to load image-loading module: %s: %s"),
312 path, g_module_error ());
313 g_free (module_name);
322 g_free (module_name);
324 image_module->module = module;
326 if (pixbuf_module_symbol (module, name, "image_load", &load_sym))
327 image_module->load = load_sym;
329 if (pixbuf_module_symbol (module, name, "image_load_xpm_data", &load_sym))
330 image_module->load_xpm_data = load_sym;
332 if (pixbuf_module_symbol (module, name, "image_begin_load", &load_sym))
333 image_module->begin_load = load_sym;
335 if (pixbuf_module_symbol (module, name, "image_stop_load", &load_sym))
336 image_module->stop_load = load_sym;
338 if (pixbuf_module_symbol (module, name, "image_load_increment", &load_sym))
339 image_module->load_increment = load_sym;
341 if (pixbuf_module_symbol (module, name, "image_load_animation", &load_sym))
342 image_module->load_animation = load_sym;
344 if (pixbuf_module_symbol (module, name, "image_save", &save_sym))
345 image_module->save = save_sym;
351 #define mname(type,fn) gdk_pixbuf__ ## type ## _image_ ##fn
352 #define m_load(type) extern GdkPixbuf * mname(type,load) (FILE *f, GError **error);
353 #define m_load_xpm_data(type) extern GdkPixbuf * mname(type,load_xpm_data) (const char **data);
354 #define m_begin_load(type) \
355 extern gpointer mname(type,begin_load) (ModulePreparedNotifyFunc prepare_func, \
356 ModuleUpdatedNotifyFunc update_func, \
357 ModuleFrameDoneNotifyFunc frame_done_func,\
358 ModuleAnimationDoneNotifyFunc anim_done_func,\
361 #define m_stop_load(type) extern void mname(type,stop_load) (gpointer context);
362 #define m_load_increment(type) extern gboolean mname(type,load_increment) (gpointer context, const guchar *buf, guint size, GError **error);
363 #define m_load_animation(type) extern GdkPixbufAnimation * mname(type,load_animation) (FILE *f, GError **error);
364 #define m_save(type) \
365 extern gboolean mname(type,save) (FILE *f, \
374 m_load_increment (png);
380 m_load_increment (bmp);
385 m_load_increment (wbmp);
390 m_load_increment (gif);
392 m_load_animation (gif);
396 m_load_increment (ico);
401 m_load_increment (jpeg);
407 m_load_increment (pnm);
412 m_load_increment (ras);
417 m_load_increment (tiff);
421 m_load_xpm_data (xpm);
424 gdk_pixbuf_load_module (GdkPixbufModule *image_module,
427 image_module->module = (void *) 1;
430 if (strcmp (image_module->module_name, "png") == 0){
431 image_module->load = mname (png,load);
432 image_module->begin_load = mname (png,begin_load);
433 image_module->load_increment = mname (png,load_increment);
434 image_module->stop_load = mname (png,stop_load);
435 image_module->save = mname (png,save);
441 if (strcmp (image_module->module_name, "bmp") == 0){
442 image_module->load = mname (bmp,load);
443 image_module->begin_load = mname (bmp,begin_load);
444 image_module->load_increment = mname (bmp,load_increment);
445 image_module->stop_load = mname (bmp,stop_load);
451 if (strcmp (image_module->module_name, "wbmp") == 0){
452 image_module->load = mname (wbmp,load);
453 image_module->begin_load = mname (wbmp,begin_load);
454 image_module->load_increment = mname (wbmp,load_increment);
455 image_module->stop_load = mname (wbmp,stop_load);
461 if (strcmp (image_module->module_name, "gif") == 0){
462 image_module->load = mname (gif,load);
463 image_module->begin_load = mname (gif,begin_load);
464 image_module->load_increment = mname (gif,load_increment);
465 image_module->stop_load = mname (gif,stop_load);
466 image_module->load_animation = mname (gif,load_animation);
472 if (strcmp (image_module->module_name, "ico") == 0){
473 image_module->load = mname (ico,load);
474 image_module->begin_load = mname (ico,begin_load);
475 image_module->load_increment = mname (ico,load_increment);
476 image_module->stop_load = mname (ico,stop_load);
482 if (strcmp (image_module->module_name, "jpeg") == 0){
483 image_module->load = mname (jpeg,load);
484 image_module->begin_load = mname (jpeg,begin_load);
485 image_module->load_increment = mname (jpeg,load_increment);
486 image_module->stop_load = mname (jpeg,stop_load);
487 image_module->save = mname (jpeg,save);
493 if (strcmp (image_module->module_name, "pnm") == 0){
494 image_module->load = mname (pnm,load);
495 image_module->begin_load = mname (pnm,begin_load);
496 image_module->load_increment = mname (pnm,load_increment);
497 image_module->stop_load = mname (pnm,stop_load);
503 if (strcmp (image_module->module_name, "ras") == 0){
504 image_module->load = mname (ras,load);
505 image_module->begin_load = mname (ras,begin_load);
506 image_module->load_increment = mname (ras,load_increment);
507 image_module->stop_load = mname (ras,stop_load);
513 if (strcmp (image_module->module_name, "tiff") == 0){
514 image_module->load = mname (tiff,load);
515 image_module->begin_load = mname (tiff,begin_load);
516 image_module->load_increment = mname (tiff,load_increment);
517 image_module->stop_load = mname (tiff,stop_load);
523 if (strcmp (image_module->module_name, "xpm") == 0){
524 image_module->load = mname (xpm,load);
525 image_module->load_xpm_data = mname (xpm,load_xpm_data);
532 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
533 _("Image type '%s' is not supported"),
534 image_module->module_name);
545 gdk_pixbuf_get_named_module (const char *name,
550 for (i = 0; file_formats [i].module_name; i++) {
551 if (!strcmp(name, file_formats[i].module_name))
552 return &(file_formats[i]);
557 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
558 _("Image type '%s' is not supported"),
565 gdk_pixbuf_get_module (guchar *buffer, guint size,
566 const gchar *filename,
571 for (i = 0; file_formats [i].module_name; i++) {
572 if ((* file_formats [i].format_check) (buffer, size))
573 return &(file_formats[i]);
579 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
580 _("Couldn't recognize the image file format for file '%s'"),
585 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
586 _("Unrecognized image file format"));
593 * gdk_pixbuf_new_from_file:
594 * @filename: Name of file to load.
595 * @error: Return location for an error
597 * Creates a new pixbuf by loading an image from a file. The file format is
598 * detected automatically. If NULL is returned, then @error will be set.
599 * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
601 * Return value: A newly-created pixbuf with a reference count of 1, or NULL if
602 * any of several error conditions occurred: the file could not be opened,
603 * there was no loader for the file's format, there was not enough memory to
604 * allocate the image buffer, or the image file contained invalid data.
607 gdk_pixbuf_new_from_file (const char *filename,
614 GdkPixbufModule *image_module;
616 g_return_val_if_fail (filename != NULL, NULL);
618 f = fopen (filename, "rb");
622 g_file_error_from_errno (errno),
623 _("Failed to open file '%s': %s"),
624 filename, g_strerror (errno));
628 size = fread (&buffer, 1, sizeof (buffer), f);
632 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
633 _("Image file '%s' contains no data"),
640 image_module = gdk_pixbuf_get_module (buffer, size, filename, error);
641 if (image_module == NULL) {
646 if (image_module->module == NULL)
647 if (!gdk_pixbuf_load_module (image_module, error)) {
652 if (image_module->load == NULL) {
655 GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
656 _("Don't know how to load the image in file '%s'"),
663 fseek (f, 0, SEEK_SET);
664 pixbuf = (* image_module->load) (f, error);
667 if (pixbuf == NULL && error != NULL && *error == NULL) {
668 /* I don't trust these crufty longjmp()'ing image libs
669 * to maintain proper error invariants, and I don't
670 * want user code to segfault as a result. We need to maintain
671 * the invariant that error gets set if NULL is returned.
674 g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
677 GDK_PIXBUF_ERROR_FAILED,
678 _("Failed to load image '%s': reason not known, probably a corrupt image file"),
681 } else if (error != NULL && *error != NULL) {
683 /* Add the filename to the error message */
689 e->message = g_strdup_printf (_("Failed to load image '%s': %s"),
699 * gdk_pixbuf_new_from_xpm_data:
700 * @data: Pointer to inline XPM data.
702 * Creates a new pixbuf by parsing XPM data in memory. This data is commonly
703 * the result of including an XPM file into a program's C source.
705 * Return value: A newly-created pixbuf with a reference count of 1.
708 gdk_pixbuf_new_from_xpm_data (const char **data)
710 GdkPixbuf *(* load_xpm_data) (const char **data);
713 if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL)
714 gdk_pixbuf_load_module (&file_formats[XPM_FILE_FORMAT_INDEX], NULL);
716 if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL) {
717 g_warning ("Can't find gdk-pixbuf module for parsing inline XPM data");
719 } else if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
720 g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
723 load_xpm_data = file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data;
725 pixbuf = (* load_xpm_data) (data);
730 collect_save_options (va_list opts,
743 next = va_arg (opts, gchar*);
747 val = va_arg (opts, gchar*);
752 *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
753 *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
755 (*keys)[count-1] = g_strdup (key);
756 (*vals)[count-1] = g_strdup (val);
758 (*keys)[count] = NULL;
759 (*vals)[count] = NULL;
761 next = va_arg (opts, gchar*);
766 gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
773 GdkPixbufModule *image_module = NULL;
775 image_module = gdk_pixbuf_get_named_module (type, error);
777 if (image_module == NULL)
780 if (image_module->module == NULL)
781 if (!gdk_pixbuf_load_module (image_module, error))
784 if (image_module->save == NULL) {
787 GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
788 _("This build of gdk-pixbuf does not support saving the image format: %s"),
793 return (* image_module->save) (filehandle, pixbuf,
801 * @pixbuf: pointer to GdkPixbuf.
802 * @filename: Name of file to save.
803 * @type: name of file format.
804 * @error: return location for error, or NULL
805 * @Varargs: list of key-value save options
807 * Saves pixbuf to a file in @type, which is currently "jpeg" or
808 * "png". If @error is set, FALSE will be returned. Possible errors include those
809 * in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
811 * The variable argument list should be NULL-terminated; if not empty,
812 * it should contain pairs of strings that modify the save
813 * parameters. For example:
816 * gdk_pixbuf_save (pixbuf, handle, "jpeg", &error,
817 * "quality", "100", NULL);
820 * The only save parameter that currently exists is the "quality" field
821 * for JPEG images; its value should be in the range [0,100].
823 * Return value: whether an error was set
827 gdk_pixbuf_save (GdkPixbuf *pixbuf,
828 const char *filename,
834 gchar **values = NULL;
838 va_start (args, error);
840 collect_save_options (args, &keys, &values);
844 result = gdk_pixbuf_savev (pixbuf, filename, type,
856 * @pixbuf: pointer to GdkPixbuf.
857 * @filename: Name of file to save.
858 * @type: name of file format.
859 * @option_keys: name of options to set, NULL-terminated
860 * @option_values: values for named options
861 * @error: return location for error, or NULL
863 * Saves pixbuf to a file in @type, which is currently "jpeg" or "png".
864 * If @error is set, FALSE will be returned. See gdk_pixbuf_save () for more
867 * Return value: whether an error was set
871 gdk_pixbuf_savev (GdkPixbuf *pixbuf,
872 const char *filename,
875 char **option_values,
882 g_return_val_if_fail (filename != NULL, FALSE);
883 g_return_val_if_fail (type != NULL, FALSE);
885 f = fopen (filename, "wb");
890 g_file_error_from_errno (errno),
891 _("Failed to open '%s' for writing: %s"),
892 filename, g_strerror (errno));
897 result = gdk_pixbuf_real_save (pixbuf, f, type,
898 option_keys, option_values,
903 g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
908 if (fclose (f) < 0) {
911 g_file_error_from_errno (errno),
912 _("Failed to close '%s' while writing image, all data may not have been saved: %s"),
913 filename, g_strerror (errno));