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