~ubuntu-branches/ubuntu/precise/gdk-pixbuf/precise-proposed

« back to all changes in this revision

Viewing changes to gdk-pixbuf/gdk-pixbuf-io.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2004-10-06 22:10:04 UTC
  • Revision ID: james.westby@ubuntu.com-20041006221004-rma9deknj8qctu67
Tags: upstream-0.22.0
ImportĀ upstreamĀ versionĀ 0.22.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 Library 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
 * Library General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Library 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.
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
#include <string.h>
 
26
#include <glib.h>
 
27
#include "gdk-pixbuf-private.h"
 
28
#include "gdk-pixbuf-io.h"
 
29
 
 
30
 
 
31
 
 
32
static gboolean
 
33
pixbuf_check_png (guchar *buffer, int size)
 
34
{
 
35
        if (size < 28)
 
36
                return FALSE;
 
37
 
 
38
        if (buffer [0] != 0x89 ||
 
39
            buffer [1] != 'P' ||
 
40
            buffer [2] != 'N' ||
 
41
            buffer [3] != 'G' ||
 
42
            buffer [4] != 0x0d ||
 
43
            buffer [5] != 0x0a ||
 
44
            buffer [6] != 0x1a ||
 
45
            buffer [7] != 0x0a)
 
46
                return FALSE;
 
47
 
 
48
        return TRUE;
 
49
}
 
50
 
 
51
static gboolean
 
52
pixbuf_check_jpeg (guchar *buffer, int size)
 
53
{
 
54
        if (size < 10)
 
55
                return FALSE;
 
56
 
 
57
        if (buffer [0] != 0xff || buffer [1] != 0xd8)
 
58
                return FALSE;
 
59
 
 
60
        return TRUE;
 
61
}
 
62
 
 
63
static gboolean
 
64
pixbuf_check_tiff (guchar *buffer, int size)
 
65
{
 
66
        if (size < 10)
 
67
                return FALSE;
 
68
 
 
69
        if (buffer [0] == 'M' &&
 
70
            buffer [1] == 'M' &&
 
71
            buffer [2] == 0   &&
 
72
            buffer [3] == 0x2a)
 
73
                return TRUE;
 
74
 
 
75
        if (buffer [0] == 'I' &&
 
76
            buffer [1] == 'I' &&
 
77
            buffer [2] == 0x2a &&
 
78
            buffer [3] == 0)
 
79
                return TRUE;
 
80
 
 
81
        return FALSE;
 
82
}
 
83
 
 
84
static gboolean
 
85
pixbuf_check_gif (guchar *buffer, int size)
 
86
{
 
87
        if (size < 20)
 
88
                return FALSE;
 
89
 
 
90
        if (strncmp (buffer, "GIF8", 4) == 0)
 
91
                return TRUE;
 
92
 
 
93
        return FALSE;
 
94
}
 
95
 
 
96
static gboolean
 
97
pixbuf_check_xpm (guchar *buffer, int size)
 
98
{
 
99
        if (size < 20)
 
100
                return FALSE;
 
101
 
 
102
        if (strncmp (buffer, "/* XPM */", 9) == 0)
 
103
                return TRUE;
 
104
 
 
105
        return FALSE;
 
106
}
 
107
 
 
108
static gboolean
 
109
pixbuf_check_pnm (guchar *buffer, int size)
 
110
{
 
111
        if (size < 20)
 
112
                return FALSE;
 
113
 
 
114
        if (buffer [0] == 'P') {
 
115
                if (buffer [1] == '1' ||
 
116
                    buffer [1] == '2' ||
 
117
                    buffer [1] == '3' ||
 
118
                    buffer [1] == '4' ||
 
119
                    buffer [1] == '5' ||
 
120
                    buffer [1] == '6')
 
121
                        return TRUE;
 
122
        }
 
123
        return FALSE;
 
124
}
 
125
static gboolean
 
126
pixbuf_check_sunras (guchar *buffer, int size)
 
127
{
 
128
        if (size < 32)
 
129
                return FALSE;
 
130
 
 
131
        if (buffer [0] != 0x59 ||
 
132
            buffer [1] != 0xA6 ||
 
133
            buffer [2] != 0x6A ||
 
134
            buffer [3] != 0x95)
 
135
                return FALSE;
 
136
 
 
137
        return TRUE;
 
138
}
 
139
 
 
140
static gboolean
 
141
pixbuf_check_ico (guchar *buffer, int size)
 
142
{
 
143
        /* Note that this may cause false positives, but .ico's don't
 
144
           have a magic number.*/
 
145
        if (size < 6)
 
146
                return FALSE;
 
147
        if (buffer [0] != 0x0 ||
 
148
            buffer [1] != 0x0 ||
 
149
            ((buffer [2] != 0x1)&&(buffer[2]!=0x2)) ||
 
150
            buffer [3] != 0x0 ||
 
151
            buffer [5] != 0x0 )
 
152
                return FALSE;
 
153
 
 
154
        return TRUE;
 
155
}
 
156
 
 
157
 
 
158
static gboolean
 
159
pixbuf_check_bmp (guchar *buffer, int size)
 
160
{
 
161
        if (size < 20)
 
162
                return FALSE;
 
163
 
 
164
        if (buffer [0] != 'B' || buffer [1] != 'M')
 
165
                return FALSE;
 
166
 
 
167
        return TRUE;
 
168
}
 
169
 
 
170
 
 
171
static gboolean
 
172
pixbuf_check_xbm (guchar *buffer, int size)
 
173
{
 
174
        if (size < 20)
 
175
                return FALSE;
 
176
 
 
177
        if (buffer [0] == '#'
 
178
            && buffer [1] == 'd'
 
179
            && buffer [2] == 'e'
 
180
            && buffer [3] == 'f'
 
181
            && buffer [4] == 'i'
 
182
            && buffer [5] == 'n'
 
183
            && buffer [6] == 'e'
 
184
            && buffer [7] == ' ')
 
185
                return TRUE;
 
186
 
 
187
        /* Note that this requires xpm to be checked before xbm. */
 
188
        if (buffer [0] == '/'
 
189
            && buffer [1] != '*')
 
190
                return TRUE;
 
191
 
 
192
        return FALSE;
 
193
}
 
194
 
 
195
static GdkPixbufModule file_formats [] = {
 
196
        { "png",  pixbuf_check_png, NULL,  NULL, NULL, NULL, NULL, NULL },
 
197
        { "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL, NULL },
 
198
        { "tiff", pixbuf_check_tiff, NULL, NULL, NULL, NULL, NULL, NULL },
 
199
        { "gif",  pixbuf_check_gif, NULL,  NULL, NULL, NULL, NULL, NULL },
 
200
#define XPM_FILE_FORMAT_INDEX 4
 
201
        { "xpm",  pixbuf_check_xpm, NULL,  NULL, NULL, NULL, NULL, NULL },
 
202
        { "pnm",  pixbuf_check_pnm, NULL,  NULL, NULL, NULL, NULL, NULL },
 
203
        { "ras",  pixbuf_check_sunras, NULL,  NULL, NULL, NULL, NULL, NULL },
 
204
        { "bmp",  pixbuf_check_bmp, NULL,  NULL, NULL, NULL, NULL, NULL },
 
205
        { "xbm",  pixbuf_check_xbm, NULL,  NULL, NULL, NULL, NULL, NULL },
 
206
        { "ico",  pixbuf_check_ico, NULL,  NULL, NULL, NULL, NULL, NULL },
 
207
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 
208
};
 
209
 
 
210
#ifdef USE_GMODULE 
 
211
static gboolean
 
212
pixbuf_module_symbol (GModule *module, const char *module_name, const char *symbol_name, gpointer *symbol)
 
213
{
 
214
        char *full_symbol_name = g_strconcat ("gdk_pixbuf__", module_name, "_", symbol_name, NULL);
 
215
        gboolean return_value;
 
216
 
 
217
        return_value = g_module_symbol (module, full_symbol_name, symbol);
 
218
        g_free (full_symbol_name);
 
219
        
 
220
        return return_value;
 
221
}
 
222
 
 
223
/* actually load the image handler - gdk_pixbuf_get_module only get a */
 
224
/* reference to the module to load, it doesn't actually load it       */
 
225
/* perhaps these actions should be combined in one function           */
 
226
void
 
227
gdk_pixbuf_load_module (GdkPixbufModule *image_module)
 
228
{
 
229
        char *module_name;
 
230
        char *path;
 
231
        GModule *module;
 
232
        gpointer load_sym;
 
233
        char *name;
 
234
        
 
235
        g_return_if_fail (image_module->module == NULL);
 
236
 
 
237
        name = image_module->module_name;
 
238
        
 
239
        module_name = g_strconcat ("pixbufloader-", name, NULL);
 
240
        path = g_module_build_path (PIXBUF_LIBDIR, module_name);
 
241
 
 
242
        module = g_module_open (path, G_MODULE_BIND_LAZY);
 
243
        if (!module) {
 
244
                /* Debug feature, check in present working directory */
 
245
                g_free (path);
 
246
                path = g_module_build_path ("", module_name);
 
247
                module = g_module_open (path, G_MODULE_BIND_LAZY);
 
248
 
 
249
                if (!module) {
 
250
                        g_warning ("Unable to load module: %s: %s", path, g_module_error ());
 
251
                        g_free (module_name);
 
252
                        g_free (path);
 
253
                        return;
 
254
                }
 
255
                g_free (path);
 
256
        } else {
 
257
                g_free (path);
 
258
        }
 
259
 
 
260
        g_free (module_name);
 
261
 
 
262
        image_module->module = module;
 
263
 
 
264
        if (pixbuf_module_symbol (module, name, "image_load", &load_sym))
 
265
                image_module->load = load_sym;
 
266
 
 
267
        if (pixbuf_module_symbol (module, name, "image_load_xpm_data", &load_sym))
 
268
                image_module->load_xpm_data = load_sym;
 
269
 
 
270
        if (pixbuf_module_symbol (module, name, "image_begin_load", &load_sym))
 
271
                image_module->begin_load = load_sym;
 
272
 
 
273
        if (pixbuf_module_symbol (module, name, "image_stop_load", &load_sym))
 
274
                image_module->stop_load = load_sym;
 
275
 
 
276
        if (pixbuf_module_symbol (module, name, "image_load_increment", &load_sym))
 
277
                image_module->load_increment = load_sym;
 
278
 
 
279
        if (pixbuf_module_symbol (module, name, "image_load_animation", &load_sym))
 
280
                image_module->load_animation = load_sym;
 
281
}
 
282
#else
 
283
 
 
284
#define mname(type,fn) gdk_pixbuf__ ## type ## _image_ ##fn
 
285
#define m_load(type)  extern GdkPixbuf * mname(type,load) (FILE *f);
 
286
#define m_load_xpm_data(type)  extern GdkPixbuf * mname(type,load_xpm_data) (const char **data);
 
287
#define m_begin_load(type)  \
 
288
   extern gpointer mname(type,begin_load) (ModulePreparedNotifyFunc prepare_func, \
 
289
                                 ModuleUpdatedNotifyFunc update_func, \
 
290
                                 ModuleFrameDoneNotifyFunc frame_done_func,\
 
291
                                 ModuleAnimationDoneNotifyFunc anim_done_func,\
 
292
                                 gpointer user_data);
 
293
#define m_stop_load(type)  extern void mname(type,stop_load) (gpointer context);
 
294
#define m_load_increment(type)  extern gboolean mname(type,load_increment) (gpointer context, const guchar *buf, guint size);
 
295
#define m_load_animation(type)  extern GdkPixbufAnimation * mname(type,load_animation) (FILE *f);
 
296
 
 
297
m_load (png);
 
298
m_begin_load (png);
 
299
m_load_increment (png);
 
300
m_stop_load (png);
 
301
m_load (bmp);
 
302
m_begin_load (bmp);
 
303
m_load_increment (bmp);
 
304
m_stop_load (bmp);
 
305
m_load (gif);
 
306
m_begin_load (gif);
 
307
m_load_increment (gif);
 
308
m_stop_load (gif);
 
309
m_load_animation (gif);
 
310
m_load (ico);
 
311
m_begin_load (ico);
 
312
m_load_increment (ico);
 
313
m_stop_load (ico);
 
314
m_load (jpeg);
 
315
m_begin_load (jpeg);
 
316
m_load_increment (jpeg);
 
317
m_stop_load (jpeg);
 
318
m_load (pnm);
 
319
m_begin_load (pnm);
 
320
m_load_increment (pnm);
 
321
m_stop_load (pnm);
 
322
m_load (ras);
 
323
m_begin_load (ras);
 
324
m_load_increment (ras);
 
325
m_stop_load (ras);
 
326
m_load (tiff);
 
327
m_begin_load (tiff);
 
328
m_load_increment (tiff);
 
329
m_stop_load (tiff);
 
330
m_load (xpm);
 
331
m_load_xpm_data (xpm);
 
332
m_load (xbm);
 
333
m_begin_load (xbm);
 
334
m_load_increment (xbm);
 
335
m_stop_load (xbm);
 
336
 
 
337
void
 
338
gdk_pixbuf_load_module (GdkPixbufModule *image_module)
 
339
{
 
340
        image_module->module = (void *) 1;
 
341
        
 
342
        if (strcmp (image_module->module_name, "png") == 0){
 
343
                image_module->load           = mname (png,load);
 
344
                image_module->begin_load     = mname (png,begin_load);
 
345
                image_module->load_increment = mname (png,load_increment);
 
346
                image_module->stop_load      = mname (png,stop_load);
 
347
                return;
 
348
        }
 
349
 
 
350
        if (strcmp (image_module->module_name, "bmp") == 0){
 
351
                image_module->load           = mname (bmp,load);
 
352
                image_module->begin_load     = mname (bmp,begin_load);
 
353
                image_module->load_increment = mname (bmp,load_increment);
 
354
                image_module->stop_load      = mname (bmp,stop_load);
 
355
                return;
 
356
        }
 
357
 
 
358
        if (strcmp (image_module->module_name, "gif") == 0){
 
359
                image_module->load           = mname (gif,load);
 
360
                image_module->begin_load     = mname (gif,begin_load);
 
361
                image_module->load_increment = mname (gif,load_increment);
 
362
                image_module->stop_load      = mname (gif,stop_load);
 
363
                image_module->load_animation = mname (gif,load_animation);
 
364
                return;
 
365
        }
 
366
 
 
367
        if (strcmp (image_module->module_name, "ico") == 0){
 
368
                image_module->load           = mname (ico,load);
 
369
                image_module->begin_load     = mname (ico,begin_load);
 
370
                image_module->load_increment = mname (ico,load_increment);
 
371
                image_module->stop_load      = mname (ico,stop_load);
 
372
                return;
 
373
        }
 
374
 
 
375
        if (strcmp (image_module->module_name, "jpeg") == 0){
 
376
                image_module->load           = mname (jpeg,load);
 
377
                image_module->begin_load     = mname (jpeg,begin_load);
 
378
                image_module->load_increment = mname (jpeg,load_increment);
 
379
                image_module->stop_load      = mname (jpeg,stop_load);
 
380
                return;
 
381
        }
 
382
        if (strcmp (image_module->module_name, "pnm") == 0){
 
383
                image_module->load           = mname (pnm,load);
 
384
                image_module->begin_load     = mname (pnm,begin_load);
 
385
                image_module->load_increment = mname (pnm,load_increment);
 
386
                image_module->stop_load      = mname (pnm,stop_load);
 
387
                return;
 
388
        }
 
389
        if (strcmp (image_module->module_name, "ras") == 0){
 
390
                image_module->load           = mname (ras,load);
 
391
                image_module->begin_load     = mname (ras,begin_load);
 
392
                image_module->load_increment = mname (ras,load_increment);
 
393
                image_module->stop_load      = mname (ras,stop_load);
 
394
                return;
 
395
        }
 
396
        if (strcmp (image_module->module_name, "tiff") == 0){
 
397
                image_module->load           = mname (tiff,load);
 
398
                image_module->begin_load     = mname (tiff,begin_load);
 
399
                image_module->load_increment = mname (tiff,load_increment);
 
400
                image_module->stop_load      = mname (tiff,stop_load);
 
401
                return;
 
402
        }
 
403
        if (strcmp (image_module->module_name, "xpm") == 0){
 
404
                image_module->load           = mname (xpm,load);
 
405
                image_module->load_xpm_data  = mname (xpm,load_xpm_data);
 
406
                return;
 
407
        }
 
408
        if (strcmp (image_module->module_name, "xbm") == 0){
 
409
                image_module->load           = mname (xbm,load);
 
410
                image_module->begin_load     = mname (xbm,begin_load);
 
411
                image_module->load_increment = mname (xbm,load_increment);
 
412
                image_module->stop_load      = mname (xbm,stop_load);
 
413
                return;
 
414
        }
 
415
}
 
416
 
 
417
 
 
418
#endif
 
419
 
 
420
 
 
421
 
 
422
GdkPixbufModule *
 
423
gdk_pixbuf_get_module (guchar *buffer, guint size)
 
424
{
 
425
        int i;
 
426
 
 
427
        for (i = 0; file_formats [i].module_name; i++) {
 
428
                if ((* file_formats [i].format_check) (buffer, size))
 
429
                        return &(file_formats[i]);
 
430
        }
 
431
 
 
432
        return NULL;
 
433
}
 
434
 
 
435
/**
 
436
 * gdk_pixbuf_new_from_file:
 
437
 * @filename: Name of file to load.
 
438
 *
 
439
 * Creates a new pixbuf by loading an image from a file.  The file format is
 
440
 * detected automatically.
 
441
 *
 
442
 * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if
 
443
 * any of several error conditions occurred:  the file could not be opened,
 
444
 * there was no loader for the file's format, there was not enough memory to
 
445
 * allocate the image buffer, or the image file contained invalid data.
 
446
 **/
 
447
GdkPixbuf *
 
448
gdk_pixbuf_new_from_file (const char *filename)
 
449
{
 
450
        GdkPixbuf *pixbuf;
 
451
        int size;
 
452
        FILE *f;
 
453
        guchar buffer [128];
 
454
        GdkPixbufModule *image_module;
 
455
 
 
456
        g_return_val_if_fail (filename != NULL, NULL);
 
457
 
 
458
        f = fopen (filename, "r");
 
459
        if (!f)
 
460
                return NULL;
 
461
 
 
462
        size = fread (&buffer, 1, sizeof (buffer), f);
 
463
        if (size == 0) {
 
464
                fclose (f);
 
465
                return NULL;
 
466
        }
 
467
 
 
468
        image_module = gdk_pixbuf_get_module (buffer, size);
 
469
        if (!image_module) {
 
470
                g_warning ("Unable to find handler for file: %s", filename);
 
471
                fclose (f);
 
472
                return NULL;
 
473
        }
 
474
 
 
475
        if (image_module->module == NULL)
 
476
                gdk_pixbuf_load_module (image_module);
 
477
 
 
478
        if (image_module->load == NULL) {
 
479
                fclose (f);
 
480
                return NULL;
 
481
        }
 
482
 
 
483
        fseek (f, 0, SEEK_SET);
 
484
        pixbuf = (* image_module->load) (f);
 
485
        fclose (f);
 
486
 
 
487
        if (pixbuf)
 
488
                g_assert (pixbuf->ref_count > 0);
 
489
 
 
490
        return pixbuf;
 
491
}
 
492
 
 
493
/**
 
494
 * gdk_pixbuf_new_from_xpm_data:
 
495
 * @data: Pointer to inline XPM data.
 
496
 *
 
497
 * Creates a new pixbuf by parsing XPM data in memory.  This data is commonly
 
498
 * the result of including an XPM file into a program's C source.
 
499
 *
 
500
 * Return value: A newly-created pixbuf with a reference count of 1.
 
501
 **/
 
502
GdkPixbuf *
 
503
gdk_pixbuf_new_from_xpm_data (const char **data)
 
504
{
 
505
        GdkPixbuf *(* load_xpm_data) (const char **data);
 
506
        GdkPixbuf *pixbuf;
 
507
 
 
508
        if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL)
 
509
                gdk_pixbuf_load_module (&file_formats[XPM_FILE_FORMAT_INDEX]);
 
510
 
 
511
        if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL) {
 
512
                g_warning ("Can't find gdk-pixbuf module for parsing inline XPM data");
 
513
                return NULL;
 
514
        } else if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
 
515
                g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
 
516
                return NULL;
 
517
        } else
 
518
                load_xpm_data = file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data;
 
519
 
 
520
        pixbuf = (* load_xpm_data) (data);
 
521
        return pixbuf;
 
522
}