1 /* +-------------------------------------------------------------------+ */
2 /* | Copyright 1993, David Koblas (koblas@netcom.com) | */
3 /* | | */
4 /* | Permission to use, copy, modify, and to distribute this software | */
5 /* | and its documentation for any purpose is hereby granted without | */
6 /* | fee, provided that the above copyright notice appear in all | */
7 /* | copies and that both that copyright notice and this permission | */
8 /* | notice appear in supporting documentation. There is no | */
9 /* | representations about the suitability of this software for | */
10 /* | any purpose. this software is provided "as is" without express | */
11 /* | or implied warranty. | */
12 /* | | */
13 /* +-------------------------------------------------------------------+ */
14
15 /* $Id: rwTable.c,v 1.22 2005/03/20 20:15:34 demailly Exp $ */
16
17 #if defined(HAVE_PARAM_H)
18 #include <sys/param.h>
19 #endif
20 #include <sys/types.h>
21 #include <sys/stat.h>
22
23 #include <stdio.h>
24 #include "image.h"
25 #include "rwTable.h"
26 #include <string.h>
27 #include <errno.h>
28
29 #ifdef MISSING_STDARG_H
30 #include <varargs.h>
31 #else
32 #include <stdarg.h>
33 #endif
34
35 typedef char *String;
36 #include "../messages.h"
37
38 #ifndef TRUE
39 #define TRUE 1
40 #define FALSE 0
41 #endif
42
43 typedef struct {
44 char *name;
45 RWreadFunc read;
46 RWwriteFunc write;
47 RWtestFunc test;
48 } ImageTypes;
49
50 static char RWtableMsg[512];
51
52 /*
53 ** Define all the read/write functions here.
54 ** [ unfortunately most compilers won't take
55 ** the "variable" name version of these. ]
56 */
57
58 extern Image *ReadPNG(char *);
59 extern int WritePNGn(char *, Image *);
60 extern int WritePNGi(char *, Image *);
61 extern int TestPNG(char *);
62
63 extern Image *ReadGIF(char *);
64 extern int WriteGIF(char *, Image *);
65 extern int TestGIF(char *);
66
67 extern Image *ReadJPEG(char *);
68 extern int WriteJPEG(char *, Image *);
69 extern int TestJPEG(char *);
70
71 extern Image *ReadJP2K(char *);
72 extern int WriteJP2K(char *, Image *);
73 extern int TestJP2K(char *);
74
75 extern Image *ReadPGF(char *);
76 extern int WritePGF(char *, Image *);
77 extern int TestPGF(char *);
78
79 extern Image *ReadTIFF(char *);
80 extern int WriteTIFF(char *, Image *);
81 extern int TestTIFF(char *);
82
83 extern Image *ReadTGA(char *);
84 extern int WriteTGA(char *, Image *);
85 extern int TestTGA(char *);
86
87 extern int TestBMP(char *);
88 extern Image *ReadBMP(char *);
89 extern int WriteBMP(char *, Image *);
90
91 extern Image *ReadICO(char *);
92 extern int WriteICO(char *, Image *);
93 extern int TestICO(char *);
94
95 extern Image *ReadSGI(char *);
96 extern int WriteSGI(char *, Image *);
97 extern int TestSGI(char *);
98
99 extern Image *ReadPNM(char *);
100 extern int WritePNM(char *, Image *);
101 extern int TestPNM(char *);
102
103 extern int TestXBM(char *);
104 extern Image *ReadXBM(char *);
105 extern int WriteXBM(char *, Image *);
106
107 extern Image *ReadXPM(char *);
108 extern int WriteXPM(char *, Image *);
109 extern int TestXPM(char *);
110
111 extern int TestXWD(char *);
112 extern Image *ReadXWD(char *);
113 extern int WriteXWD(char *, Image *);
114
115 extern int TestLXP(char *);
116 extern Image *ReadLXP(char *);
117 extern int WriteLXP(char *, Image *);
118
119 extern Image *ReadPS_(char *);
120 extern int WritePS(char *, Image *);
121 extern int WritePDF(char *, Image *);
122 extern int TestPS_(char *);
123
124 extern Image *ReadScriptC(char *);
125 extern int TestScriptC(char *);
126
127 #define DEF_READ_ENTRY 0
128 #define DEF_WRITE_ENTRY 0
129
130 /* GRR 960219: added PNG, alphabetized image types: */
131 static ImageTypes RWtable[] =
132 {
133 {"Auto_Detect", readMagic, writeMagic, NULL },
134 #ifdef HAVE_PNG /* ReadPNG does all PNG files; no need for two entries */
135 {"PNG_Format", ReadPNG, WritePNGn, TestPNG },
136 {"PNG_Interlaced", NULL, WritePNGi, TestPNG },
137 #endif
138 {"GIF_Format", ReadGIF, WriteGIF, TestGIF },
139 #ifdef HAVE_JPEG
140 {"JPEG_Format", ReadJPEG, WriteJPEG, TestJPEG},
141 #endif
142 #if defined(HAVE_OPENJPEG) || defined(HAVE_JASPER)
143 {"JP2K_Format", ReadJP2K, WriteJP2K, TestJP2K},
144 #endif
145 #ifdef HAVE_PGF
146 {"PGF_Format", ReadPGF, WritePGF, TestPGF},
147 #endif
148 #ifdef HAVE_TIFF
149 {"TIFF_Format", ReadTIFF, WriteTIFF, TestTIFF},
150 #endif
151 {"TGA_Format", ReadTGA, WriteTGA, TestTGA },
152 {"BMP_Format", ReadBMP, WriteBMP, TestBMP },
153 #ifdef HAVE_ICO
154 {"ICO_Format", ReadICO, WriteICO, TestICO },
155 #endif
156 #ifdef HAVE_SGI
157 {"SGI_Format", ReadSGI, WriteSGI, TestSGI },
158 #endif
159 {"PPM_Format", ReadPNM, WritePNM, TestPNM },
160 {"XBM_Format", ReadXBM, WriteXBM, TestXBM },
161 {"XPM_Format", ReadXPM, WriteXPM, TestXPM },
162 {"XWD_Format", ReadXWD, WriteXWD, TestXWD },
163 {"LXP_Format", ReadLXP, WriteLXP, TestLXP },
164 {"PS_Format", ReadPS_, WritePS, TestPS_ },
165 {"PDF_Format", ReadPS_, WritePDF, TestPS_ },
166 {"TEX_Format", ReadPS_, NULL, TestPS_ },
167 {"CSC_Format", ReadScriptC, NULL, TestScriptC }
168 };
169
170 #define FMT_NUMBER (sizeof(RWtable) / sizeof(RWtable[0]))
171
172 static char *readList[FMT_NUMBER + 1];
173 static char *writeList[FMT_NUMBER + 1];
174
175 /*
176 ** Special reader that uses the above information.
177 */
178 static char *usedMagicReader = NULL;
179 int file_isSpecialImage;
180 int file_numpages;
181 int file_force = 1;
182 int file_bbox = 1;
183 int file_transparent = 0;
184 int file_specified_zoom = 0;
185
186 RWwriteFunc
RWtableGetWriterFromSuffix(char * suffix)187 RWtableGetWriterFromSuffix(char *suffix)
188 {
189 int i;
190 if (!suffix || !*suffix) return WritePNGn;
191 if (!strcasecmp(suffix, "C")) suffix = "CSC";
192 if (!strcasecmp(suffix, "JPG")) suffix = "JPEG";
193
194 for (i = 1; i < FMT_NUMBER; i++) {
195 if (!strncasecmp(RWtable[i].name, suffix, strlen(suffix)) &&
196 RWtable[i].write)
197 return RWtable[i].write;
198 }
199 /* default to WritePNG otherwise */
200 return WritePNGn;
201 }
202
203 int
testMagic(char * file)204 testMagic(char *file)
205 {
206 int i, i_tga = -1;
207
208 errno = 0;
209
210 for (i = 0 ; i <= FMT_NUMBER; i++) {
211 /* Ensure that TGA is the last one by skipping it first ... */
212 if (i == FMT_NUMBER) {
213 if (i_tga < 0) break;
214 i = i_tga;
215 } else
216 if (!strncmp(RWtable[i].name, "TGA", 3)) {
217 i_tga = i;
218 continue;
219 }
220 if (RWtable[i].read == NULL || RWtable[i].test == NULL ||
221 !RWtable[i].test(file)) {
222 if (i == i_tga) break;
223 continue;
224 }
225 return 1;
226 }
227 return 0;
228 }
229
230 Image *
readMagic(char * file)231 readMagic(char *file)
232 {
233 int i, i_tga = -1;
234
235 errno = 0;
236 file_isSpecialImage = 0;
237 file_transparent = 0;
238 file_numpages = 1;
239 file_specified_zoom = 0;
240
241 for (i = 0 ; i <= FMT_NUMBER; i++) {
242 /* Ensure that TGA is the last one by skipping it first ... */
243 if (i == FMT_NUMBER) {
244 if (i_tga < 0) break;
245 i = i_tga;
246 } else
247 if (!strncmp(RWtable[i].name, "TGA", 3)) {
248 i_tga = i;
249 continue;
250 }
251 if (RWtable[i].read == NULL || RWtable[i].test == NULL ||
252 !RWtable[i].test(file)) {
253 if (i == i_tga) break;
254 continue;
255 }
256 usedMagicReader = RWtable[i].name;
257 return RWtable[i].read(file);
258 }
259
260 if (errno == 0)
261 RWSetMsg(msgText[UNKNOWN_IMAGE_FORMAT]);
262
263 return NULL;
264 }
265
266 int
writeMagic(char * file,Image * image)267 writeMagic(char *file, Image *image)
268 {
269 RWwriteFunc proc;
270 char *ptr;
271 ptr = strrchr(file, '.');
272 if (ptr) {
273 ++ptr;
274 proc = RWtableGetWriterFromSuffix(ptr);
275 } else
276 proc = WritePNGn;
277 return proc(file, image);
278 }
279
280 void *
RWtableGetReaderID()281 RWtableGetReaderID()
282 {
283 return (void *) usedMagicReader;
284 }
285
286
287 /*
288 ** Give a name, return an "opaque" handle to some information
289 */
290 void *
RWtableGetEntry(char * name)291 RWtableGetEntry(char *name)
292 {
293 int i;
294
295 for (i = 0; i < FMT_NUMBER; i++)
296 if (strcmp(name, RWtable[i].name) == 0)
297 return (void *) &RWtable[i];
298 return NULL;
299 }
300
301 char *
RWtableGetId(void * v)302 RWtableGetId(void *v)
303 {
304 ImageTypes *entry = (ImageTypes *) v;
305
306 if (entry == NULL)
307 return NULL;
308
309 return entry->name;
310 }
311
312 RWreadFunc
RWtableGetReader(void * entry)313 RWtableGetReader(void *entry)
314 {
315 RWtableMsg[0] = '\0';
316
317 if (entry == NULL)
318 return RWtable[DEF_READ_ENTRY].read;
319
320 return ((ImageTypes *) entry)->read;
321 }
322
323 RWwriteFunc
RWtableGetWriter(void * entry)324 RWtableGetWriter(void *entry)
325 {
326 RWtableMsg[0] = '\0';
327
328 if (entry == NULL)
329 return RWtable[DEF_WRITE_ENTRY].write;
330
331 return ((ImageTypes *) entry)->write;
332 }
333
334 char **
RWtableGetReaderList()335 RWtableGetReaderList()
336 {
337 static int done = FALSE;
338 int i, idx = 0;
339
340 if (!done) {
341 for (i = 0; i < FMT_NUMBER; i++)
342 if (RWtable[i].read != NULL)
343 readList[idx++] = RWtable[i].name;
344 readList[idx++] = NULL;
345 done = TRUE;
346 }
347 return readList;
348 }
349
350 char **
RWtableGetWriterList()351 RWtableGetWriterList()
352 {
353 static int done = FALSE;
354 int i, idx = 0;
355
356 if (!done) {
357 for (i = 0; i < FMT_NUMBER; i++)
358 if (RWtable[i].write != NULL)
359 writeList[idx++] = RWtable[i].name;
360 writeList[idx++] = NULL;
361 done = TRUE;
362 }
363 return writeList;
364 }
365
366 char *
RWGetMsg()367 RWGetMsg()
368 {
369 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
370 #if defined(BSD4_4)
371 __const extern char *__const sys_errlist[];
372 #else
373 #ifndef __GLIBC__
374 #ifndef SYS_ERRLIST_DEFINED
375 #ifdef __CYGWIN__
376 # define sys_errlist _sys_errlist
377 #else
378 extern char *sys_errlist[];
379 #endif
380 #endif
381 #endif
382 #endif
383 #endif
384
385 if (RWtableMsg[0] == '\0') {
386 if (errno == 0)
387 return "";
388 #if defined(__STDC__) && !defined(MISSING_STRERROR)
389 return strerror(errno);
390 #else
391 return sys_errlist[errno];
392 #endif
393 }
394 return RWtableMsg;
395 }
396
397 #ifdef MISSING_STDARG_H
RWSetMsg(va_alist)398 void RWSetMsg(va_alist)
399 va_dcl
400 {
401 va_list ap;
402 char *fmt;
403
404 va_start(ap);
405 fmt = va_arg(ap, char *);
406 vsprintf(RWtableMsg, fmt, ap);
407 }
408
409 #else
RWSetMsg(char * fmt,...)410 void RWSetMsg(char *fmt, ...)
411 {
412 va_list ap;
413
414 va_start(ap, fmt);
415 vsprintf(RWtableMsg, fmt, ap);
416 }
417 #endif
418
419 Image *
ImageFromFile(char * file)420 ImageFromFile(char *file)
421 {
422 return readMagic(file);
423 }
424