]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/gdk-pixbuf-io.c
Massive update...
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-io.c
1 /*
2  * gdk-pixbuf-io.c: Code to load images into GdkPixBufs
3  *
4  * Author:
5  *    Miguel de Icaza (miguel@gnu.org)
6  */
7 #include <config.h>
8 #include <stdio.h>
9 #include <glib.h>
10 #include <gmodule.h>
11 #include "gdk-pixbuf.h"
12
13 #define PIXBUF_LIBDIR "."
14
15 static gboolean
16 pixbuf_check_png (unsigned char *buffer, int size)
17 {
18         if (size < 28)
19                 return FALSE;
20
21         if (buffer [0] != 0x89 ||
22             buffer [1] != 'P' ||
23             buffer [2] != 'N' ||
24             buffer [3] != 'G' ||
25             buffer [4] != 0x0d ||
26             buffer [5] != 0x0a ||
27             buffer [6] != 0x1a ||
28             buffer [7] != 0x0a)
29                 return FALSE;
30
31         return TRUE;
32 }
33
34 static gboolean
35 pixbuf_check_jpeg (unsigned char *buffer, int size)
36 {
37         if (size < 10)
38                 return FALSE;
39
40         if (buffer [0] != 0xff || buffer [1] != 0xd8)
41                 return FALSE;
42         
43         return TRUE;
44 }
45
46 static gboolean
47 pixbuf_check_tiff (unsigned char *buffer, int size)
48 {
49         if (size < 10)
50                 return FALSE;
51
52         if (buffer [0] == 'M' && buffer [1] == 'M' && buffer [2] == 0 && buffer [3] == 0x2a)
53                 return TRUE;
54
55         if (buffer [0] == 'I' && buffer [1] == 'I' && buffer [2] == 0x2a && buffer [3] == 0)
56                 return TRUE;
57         
58         return FALSE;
59 }
60
61 static gboolean
62 pixbuf_check_gif (unsigned char *buffer, int size)
63 {
64         if (size < 20)
65                 return FALSE;
66                 
67         if (strncmp (buffer, "GIF8", 4) == 0)
68                 return TRUE;
69         
70         return FALSE;
71 }
72
73 static gboolean
74 pixbuf_check_xpm (unsigned char *buffer, int size)
75 {
76         if (size < 20)
77                 return FALSE;
78         
79         if (strncmp (buffer, "/* XPM */", 9) == 0)
80                 return TRUE;
81         
82         return FALSE;
83 }
84
85 static gboolean
86 pixbuf_check_bmp (unsigned char *buffer, int size)
87 {
88         if (size < 20)
89                 return FALSE;
90         
91         if (buffer [0] != 'B' || buffer [1] != 'M')
92                 return FALSE;
93         
94         return TRUE;
95 }
96
97 static gboolean
98 pixbuf_check_ppm (unsigned char *buffer, int size)
99 {
100         if (size < 20)
101                 return FALSE;
102
103         if (buffer [0] == 'P'){
104                 if (buffer [1] == '1' ||
105                     buffer [1] == '2' ||
106                     buffer [1] == '3' ||
107                     buffer [1] == '4' ||
108                     buffer [1] == '5' ||
109                     buffer [1] == '6')
110                         return TRUE;
111         }
112         return FALSE;
113 }
114
115 static struct {
116         char      *module_name;
117         gboolean   (*format_check)(unsigned char *buffer, int size);
118         GModule   *module;
119         GdkPixBuf *(*load)(FILE *f);
120         int        (*save)(char *filename, ...);
121 } file_formats [] = {
122         { "png",  pixbuf_check_png,  NULL, NULL, NULL },
123         { "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL },
124         { "tiff", pixbuf_check_tiff, NULL, NULL, NULL },
125         { "gif",  pixbuf_check_gif,  NULL, NULL, NULL },
126         { "xpm",  pixbuf_check_xpm,  NULL, NULL, NULL },
127 /*      { "bmp",  pixbuf_check_bmp,  NULL, NULL, NULL },
128         { "ppm",  pixbuf_check_ppm,  NULL, NULL, NULL },*/
129         { NULL, NULL, NULL, NULL, NULL }
130 };
131
132 static int
133 image_file_format (const char *file)
134 {
135         FILE *f = fopen (file, "r");
136
137         if (!f)
138                 return -1;
139 }
140
141 static void
142 image_handler_load (int idx)
143 {
144         char *module_name = g_strconcat ("pixbuf-", file_formats [idx].module_name, NULL);
145         char *path;
146         GModule *module;
147         void *load_sym, *save_sym;
148         
149         path = g_module_build_path (PIXBUF_LIBDIR, module_name);
150         g_free (module_name);
151
152         module = g_module_open (path, G_MODULE_BIND_LAZY);
153         if (!module)
154                 return;
155         
156         file_formats [idx].module = module;
157
158         if (g_module_symbol (module, "image_load", &load_sym))
159                 file_formats [idx].load = load_sym;
160
161         if (g_module_symbol (module, "image_save", &save_sym))
162                 file_formats [idx].save = save_sym;
163 }
164
165 GdkPixBuf *
166 gdk_pixbuf_load_image (const char *file)
167 {
168         GdkPixBuf *pixbuf;
169         gint n, i;
170         FILE *f;
171         char buffer [128];
172
173         f = fopen (file, "r");
174         if (!f)
175                 return NULL;
176         n = fread (&buffer, 1, sizeof (buffer), f);
177
178         if (n == 0){
179                 fclose (f);             
180                 return NULL;
181         }
182
183         for (i = 0; file_formats [i].module_name; i++){
184                 if ((*file_formats [i].format_check)(buffer, n)){
185                         if (!file_formats [i].load)
186                                 image_handler_load (i);
187
188                         if (!file_formats [i].load){
189                                 fclose (f);
190                                 return NULL;
191                         }
192
193                         fseek(f, 0, SEEK_SET);
194                         pixbuf = (*file_formats [i].load)(f);
195                         fclose (f);
196                         return pixbuf;
197                 }
198         }
199
200         fclose (f);
201         return NULL;
202 }
203