]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/tif_open.c
The mmedia contrib requires sys/soundcard.h on unix, so disable it on unix
[wxWidgets.git] / src / tiff / tif_open.c
1 /* $Header$ */
2
3 /*
4 * Copyright (c) 1988-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and
8 * its documentation for any purpose is hereby granted without fee, provided
9 * that (i) the above copyright notices and this permission notice appear in
10 * all copies of the software and related documentation, and (ii) the names of
11 * Sam Leffler and Silicon Graphics may not be used in any advertising or
12 * publicity relating to the software without the specific, prior written
13 * permission of Sam Leffler and Silicon Graphics.
14 *
15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 */
26
27 /*
28 * TIFF Library.
29 */
30 #include "tiffiop.h"
31
32 void _TIFFSetDefaultCompressionState(TIFF* tif);
33
34 static const long typemask[13] = {
35 (long)0L, /* TIFF_NOTYPE */
36 (long)0x000000ffL, /* TIFF_BYTE */
37 (long)0xffffffffL, /* TIFF_ASCII */
38 (long)0x0000ffffL, /* TIFF_SHORT */
39 (long)0xffffffffL, /* TIFF_LONG */
40 (long)0xffffffffL, /* TIFF_RATIONAL */
41 (long)0x000000ffL, /* TIFF_SBYTE */
42 (long)0x000000ffL, /* TIFF_UNDEFINED */
43 (long)0x0000ffffL, /* TIFF_SSHORT */
44 (long)0xffffffffL, /* TIFF_SLONG */
45 (long)0xffffffffL, /* TIFF_SRATIONAL */
46 (long)0xffffffffL, /* TIFF_FLOAT */
47 (long)0xffffffffL, /* TIFF_DOUBLE */
48 };
49 static const int bigTypeshift[13] = {
50 0, /* TIFF_NOTYPE */
51 24, /* TIFF_BYTE */
52 0, /* TIFF_ASCII */
53 16, /* TIFF_SHORT */
54 0, /* TIFF_LONG */
55 0, /* TIFF_RATIONAL */
56 24, /* TIFF_SBYTE */
57 24, /* TIFF_UNDEFINED */
58 16, /* TIFF_SSHORT */
59 0, /* TIFF_SLONG */
60 0, /* TIFF_SRATIONAL */
61 0, /* TIFF_FLOAT */
62 0, /* TIFF_DOUBLE */
63 };
64 static const int litTypeshift[13] = {
65 0, /* TIFF_NOTYPE */
66 0, /* TIFF_BYTE */
67 0, /* TIFF_ASCII */
68 0, /* TIFF_SHORT */
69 0, /* TIFF_LONG */
70 0, /* TIFF_RATIONAL */
71 0, /* TIFF_SBYTE */
72 0, /* TIFF_UNDEFINED */
73 0, /* TIFF_SSHORT */
74 0, /* TIFF_SLONG */
75 0, /* TIFF_SRATIONAL */
76 0, /* TIFF_FLOAT */
77 0, /* TIFF_DOUBLE */
78 };
79
80 /*
81 * Initialize the shift & mask tables, and the
82 * byte swapping state according to the file
83 * contents and the machine architecture.
84 */
85 static void
86 TIFFInitOrder(TIFF* tif, int magic, int bigendian)
87 {
88 tif->tif_typemask = typemask;
89 if (magic == TIFF_BIGENDIAN) {
90 tif->tif_typeshift = bigTypeshift;
91 if (!bigendian)
92 tif->tif_flags |= TIFF_SWAB;
93 } else {
94 tif->tif_typeshift = litTypeshift;
95 if (bigendian)
96 tif->tif_flags |= TIFF_SWAB;
97 }
98 }
99
100 int
101 _TIFFgetMode(const char* mode, const char* module)
102 {
103 int m = -1;
104
105 switch (mode[0]) {
106 case 'r':
107 m = O_RDONLY;
108 if (mode[1] == '+')
109 m = O_RDWR;
110 break;
111 case 'w':
112 case 'a':
113 m = O_RDWR|O_CREAT;
114 if (mode[0] == 'w')
115 m |= O_TRUNC;
116 break;
117 default:
118 TIFFError(module, "\"%s\": Bad mode", mode);
119 break;
120 }
121 return (m);
122 }
123
124 TIFF*
125 TIFFClientOpen(
126 const char* name, const char* mode,
127 thandle_t clientdata,
128 TIFFReadWriteProc readproc,
129 TIFFReadWriteProc writeproc,
130 TIFFSeekProc seekproc,
131 TIFFCloseProc closeproc,
132 TIFFSizeProc sizeproc,
133 TIFFMapFileProc mapproc,
134 TIFFUnmapFileProc unmapproc
135 )
136 {
137 static const char module[] = "TIFFClientOpen";
138 TIFF *tif;
139 int m, bigendian;
140 const char* cp;
141
142 m = _TIFFgetMode(mode, module);
143 if (m == -1)
144 goto bad2;
145 tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
146 if (tif == NULL) {
147 TIFFError(module, "%s: Out of memory (TIFF structure)", name);
148 goto bad2;
149 }
150 _TIFFmemset(tif, 0, sizeof (*tif));
151 tif->tif_name = (char *)tif + sizeof (TIFF);
152 strcpy(tif->tif_name, name);
153 tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
154 tif->tif_curdir = (tdir_t) -1; /* non-existent directory */
155 tif->tif_curoff = 0;
156 tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */
157 tif->tif_row = (uint32) -1; /* read/write pre-increment */
158 tif->tif_clientdata = clientdata;
159 if (!readproc || !writeproc || !seekproc || !closeproc
160 || !sizeproc || !mapproc || !unmapproc) {
161 TIFFError(module, "One of the client procedures are NULL pointer");
162 goto bad3;
163 }
164 tif->tif_readproc = readproc;
165 tif->tif_writeproc = writeproc;
166 tif->tif_seekproc = seekproc;
167 tif->tif_closeproc = closeproc;
168 tif->tif_sizeproc = sizeproc;
169 tif->tif_mapproc = mapproc;
170 tif->tif_unmapproc = unmapproc;
171 _TIFFSetDefaultCompressionState(tif); /* setup default state */
172 /*
173 * Default is to return data MSB2LSB and enable the
174 * use of memory-mapped files and strip chopping when
175 * a file is opened read-only.
176 */
177 tif->tif_flags = FILLORDER_MSB2LSB;
178 if (m == O_RDONLY )
179 tif->tif_flags |= TIFF_MAPPED;
180
181 #ifdef STRIPCHOP_DEFAULT
182 if (m == O_RDONLY || m == O_RDWR)
183 tif->tif_flags |= STRIPCHOP_DEFAULT;
184 #endif
185
186 { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
187 /*
188 * Process library-specific flags in the open mode string.
189 * The following flags may be used to control intrinsic library
190 * behaviour that may or may not be desirable (usually for
191 * compatibility with some application that claims to support
192 * TIFF but only supports some braindead idea of what the
193 * vendor thinks TIFF is):
194 *
195 * 'l' use little-endian byte order for creating a file
196 * 'b' use big-endian byte order for creating a file
197 * 'L' read/write information using LSB2MSB bit order
198 * 'B' read/write information using MSB2LSB bit order
199 * 'H' read/write information using host bit order
200 * 'M' enable use of memory-mapped files when supported
201 * 'm' disable use of memory-mapped files
202 * 'C' enable strip chopping support when reading
203 * 'c' disable strip chopping support
204 *
205 * The use of the 'l' and 'b' flags is strongly discouraged.
206 * These flags are provided solely because numerous vendors,
207 * typically on the PC, do not correctly support TIFF; they
208 * only support the Intel little-endian byte order. This
209 * support is not configured by default because it supports
210 * the violation of the TIFF spec that says that readers *MUST*
211 * support both byte orders. It is strongly recommended that
212 * you not use this feature except to deal with busted apps
213 * that write invalid TIFF. And even in those cases you should
214 * bang on the vendors to fix their software.
215 *
216 * The 'L', 'B', and 'H' flags are intended for applications
217 * that can optimize operations on data by using a particular
218 * bit order. By default the library returns data in MSB2LSB
219 * bit order for compatibiltiy with older versions of this
220 * library. Returning data in the bit order of the native cpu
221 * makes the most sense but also requires applications to check
222 * the value of the FillOrder tag; something they probabyl do
223 * not do right now.
224 *
225 * The 'M' and 'm' flags are provided because some virtual memory
226 * systems exhibit poor behaviour when large images are mapped.
227 * These options permit clients to control the use of memory-mapped
228 * files on a per-file basis.
229 *
230 * The 'C' and 'c' flags are provided because the library support
231 * for chopping up large strips into multiple smaller strips is not
232 * application-transparent and as such can cause problems. The 'c'
233 * option permits applications that only want to look at the tags,
234 * for example, to get the unadulterated TIFF tag information.
235 */
236 for (cp = mode; *cp; cp++)
237 switch (*cp) {
238 case 'b':
239 if ((m&O_CREAT) && !bigendian)
240 tif->tif_flags |= TIFF_SWAB;
241 break;
242 case 'l':
243 if ((m&O_CREAT) && bigendian)
244 tif->tif_flags |= TIFF_SWAB;
245 break;
246 case 'B':
247 tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
248 FILLORDER_MSB2LSB;
249 break;
250 case 'L':
251 tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
252 FILLORDER_LSB2MSB;
253 break;
254 case 'H':
255 tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
256 HOST_FILLORDER;
257 break;
258 case 'M':
259 if (m == O_RDONLY)
260 tif->tif_flags |= TIFF_MAPPED;
261 break;
262 case 'm':
263 if (m == O_RDONLY)
264 tif->tif_flags &= ~TIFF_MAPPED;
265 break;
266 case 'C':
267 if (m == O_RDONLY)
268 tif->tif_flags |= TIFF_STRIPCHOP;
269 break;
270 case 'c':
271 if (m == O_RDONLY)
272 tif->tif_flags &= ~TIFF_STRIPCHOP;
273 break;
274 }
275 /*
276 * Read in TIFF header.
277 */
278 if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
279 if (tif->tif_mode == O_RDONLY) {
280 TIFFError(name, "Cannot read TIFF header");
281 goto bad;
282 }
283 /*
284 * Setup header and write.
285 */
286 tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
287 ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
288 : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);
289 tif->tif_header.tiff_version = TIFF_VERSION;
290 if (tif->tif_flags & TIFF_SWAB)
291 TIFFSwabShort(&tif->tif_header.tiff_version);
292 tif->tif_header.tiff_diroff = 0; /* filled in later */
293
294 /*
295 * This seek shouldn't be necessary, but I have had some
296 * crazy problems with a failed fseek() on Solaris leaving
297 * the current file pointer out of whack when an fwrite()
298 * is done.
299 */
300 TIFFSeekFile( tif, 0, SEEK_SET );
301
302 if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
303 TIFFError(name, "Error writing TIFF header");
304 goto bad;
305 }
306 /*
307 * Setup the byte order handling.
308 */
309 TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
310 /*
311 * Setup default directory.
312 */
313 if (!TIFFDefaultDirectory(tif))
314 goto bad;
315 tif->tif_diroff = 0;
316 tif->tif_dirlist = NULL;
317 tif->tif_dirnumber = 0;
318 return (tif);
319 }
320 /*
321 * Setup the byte order handling.
322 */
323 if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
324 tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
325 TIFFError(name, "Not a TIFF file, bad magic number %d (0x%x)",
326 tif->tif_header.tiff_magic,
327 tif->tif_header.tiff_magic);
328 goto bad;
329 }
330 TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
331 /*
332 * Swap header if required.
333 */
334 if (tif->tif_flags & TIFF_SWAB) {
335 TIFFSwabShort(&tif->tif_header.tiff_version);
336 TIFFSwabLong(&tif->tif_header.tiff_diroff);
337 }
338 /*
339 * Now check version (if needed, it's been byte-swapped).
340 * Note that this isn't actually a version number, it's a
341 * magic number that doesn't change (stupid).
342 */
343 if (tif->tif_header.tiff_version != TIFF_VERSION) {
344 TIFFError(name,
345 "Not a TIFF file, bad version number %d (0x%x)",
346 tif->tif_header.tiff_version,
347 tif->tif_header.tiff_version);
348 goto bad;
349 }
350 tif->tif_flags |= TIFF_MYBUFFER;
351 tif->tif_rawcp = tif->tif_rawdata = 0;
352 tif->tif_rawdatasize = 0;
353 /*
354 * Setup initial directory.
355 */
356 switch (mode[0]) {
357 case 'r':
358 tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
359 /*
360 * Try to use a memory-mapped file if the client
361 * has not explicitly suppressed usage with the
362 * 'm' flag in the open mode (see above).
363 */
364 if ((tif->tif_flags & TIFF_MAPPED) &&
365 !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
366 tif->tif_flags &= ~TIFF_MAPPED;
367 if (TIFFReadDirectory(tif)) {
368 tif->tif_rawcc = -1;
369 tif->tif_flags |= TIFF_BUFFERSETUP;
370 return (tif);
371 }
372 break;
373 case 'a':
374 /*
375 * New directories are automatically append
376 * to the end of the directory chain when they
377 * are written out (see TIFFWriteDirectory).
378 */
379 if (!TIFFDefaultDirectory(tif))
380 goto bad;
381 return (tif);
382 }
383 bad:
384 tif->tif_mode = O_RDONLY; /* XXX avoid flush */
385 TIFFClose(tif);
386 return ((TIFF*)0);
387 bad2:
388 (void) (*closeproc)(clientdata);
389 bad3:
390 return ((TIFF*)0);
391 }
392
393 /*
394 * Query functions to access private data.
395 */
396
397 /*
398 * Return open file's name.
399 */
400 const char *
401 TIFFFileName(TIFF* tif)
402 {
403 return (tif->tif_name);
404 }
405
406 /*
407 * Return open file's I/O descriptor.
408 */
409 int
410 TIFFFileno(TIFF* tif)
411 {
412 return (tif->tif_fd);
413 }
414
415 /*
416 * Return read/write mode.
417 */
418 int
419 TIFFGetMode(TIFF* tif)
420 {
421 return (tif->tif_mode);
422 }
423
424 /*
425 * Return nonzero if file is organized in
426 * tiles; zero if organized as strips.
427 */
428 int
429 TIFFIsTiled(TIFF* tif)
430 {
431 return (isTiled(tif));
432 }
433
434 /*
435 * Return current row being read/written.
436 */
437 uint32
438 TIFFCurrentRow(TIFF* tif)
439 {
440 return (tif->tif_row);
441 }
442
443 /*
444 * Return index of the current directory.
445 */
446 tdir_t
447 TIFFCurrentDirectory(TIFF* tif)
448 {
449 return (tif->tif_curdir);
450 }
451
452 /*
453 * Return current strip.
454 */
455 tstrip_t
456 TIFFCurrentStrip(TIFF* tif)
457 {
458 return (tif->tif_curstrip);
459 }
460
461 /*
462 * Return current tile.
463 */
464 ttile_t
465 TIFFCurrentTile(TIFF* tif)
466 {
467 return (tif->tif_curtile);
468 }
469
470 /*
471 * Return nonzero if the file has byte-swapped data.
472 */
473 int
474 TIFFIsByteSwapped(TIFF* tif)
475 {
476 return ((tif->tif_flags & TIFF_SWAB) != 0);
477 }
478
479 /*
480 * Return nonzero if the data is returned up-sampled.
481 */
482 int
483 TIFFIsUpSampled(TIFF* tif)
484 {
485 return (isUpSampled(tif));
486 }
487
488 /*
489 * Return nonzero if the data is returned in MSB-to-LSB bit order.
490 */
491 int
492 TIFFIsMSB2LSB(TIFF* tif)
493 {
494 return (isFillOrder(tif, FILLORDER_MSB2LSB));
495 }