]>
Commit | Line | Data |
---|---|---|
b47c832e RR |
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 | 0L, /* TIFF_NOTYPE */ | |
36 | 0x000000ffL, /* TIFF_BYTE */ | |
37 | 0xffffffffL, /* TIFF_ASCII */ | |
38 | 0x0000ffffL, /* TIFF_SHORT */ | |
39 | 0xffffffffL, /* TIFF_LONG */ | |
40 | 0xffffffffL, /* TIFF_RATIONAL */ | |
41 | 0x000000ffL, /* TIFF_SBYTE */ | |
42 | 0x000000ffL, /* TIFF_UNDEFINED */ | |
43 | 0x0000ffffL, /* TIFF_SSHORT */ | |
44 | 0xffffffffL, /* TIFF_SLONG */ | |
45 | 0xffffffffL, /* TIFF_SRATIONAL */ | |
46 | 0xffffffffL, /* TIFF_FLOAT */ | |
47 | 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 | tif->tif_readproc = readproc; | |
160 | tif->tif_writeproc = writeproc; | |
161 | tif->tif_seekproc = seekproc; | |
162 | tif->tif_closeproc = closeproc; | |
163 | tif->tif_sizeproc = sizeproc; | |
164 | tif->tif_mapproc = mapproc; | |
165 | tif->tif_unmapproc = unmapproc; | |
166 | _TIFFSetDefaultCompressionState(tif); /* setup default state */ | |
167 | /* | |
168 | * Default is to return data MSB2LSB and enable the | |
169 | * use of memory-mapped files and strip chopping when | |
170 | * a file is opened read-only. | |
171 | */ | |
172 | tif->tif_flags = FILLORDER_MSB2LSB; | |
173 | if (m == O_RDONLY) | |
174 | #ifdef STRIPCHOP_DEFAULT | |
175 | tif->tif_flags |= TIFF_MAPPED|STRIPCHOP_DEFAULT; | |
176 | #else | |
177 | tif->tif_flags |= TIFF_MAPPED; | |
178 | #endif | |
179 | ||
180 | { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; } | |
181 | /* | |
182 | * Process library-specific flags in the open mode string. | |
183 | * The following flags may be used to control intrinsic library | |
184 | * behaviour that may or may not be desirable (usually for | |
185 | * compatibility with some application that claims to support | |
186 | * TIFF but only supports some braindead idea of what the | |
187 | * vendor thinks TIFF is): | |
188 | * | |
189 | * 'l' use little-endian byte order for creating a file | |
190 | * 'b' use big-endian byte order for creating a file | |
191 | * 'L' read/write information using LSB2MSB bit order | |
192 | * 'B' read/write information using MSB2LSB bit order | |
193 | * 'H' read/write information using host bit order | |
194 | * 'M' enable use of memory-mapped files when supported | |
195 | * 'm' disable use of memory-mapped files | |
196 | * 'C' enable strip chopping support when reading | |
197 | * 'c' disable strip chopping support | |
198 | * | |
199 | * The use of the 'l' and 'b' flags is strongly discouraged. | |
200 | * These flags are provided solely because numerous vendors, | |
201 | * typically on the PC, do not correctly support TIFF; they | |
202 | * only support the Intel little-endian byte order. This | |
203 | * support is not configured by default because it supports | |
204 | * the violation of the TIFF spec that says that readers *MUST* | |
205 | * support both byte orders. It is strongly recommended that | |
206 | * you not use this feature except to deal with busted apps | |
207 | * that write invalid TIFF. And even in those cases you should | |
208 | * bang on the vendors to fix their software. | |
209 | * | |
210 | * The 'L', 'B', and 'H' flags are intended for applications | |
211 | * that can optimize operations on data by using a particular | |
212 | * bit order. By default the library returns data in MSB2LSB | |
213 | * bit order for compatibiltiy with older versions of this | |
214 | * library. Returning data in the bit order of the native cpu | |
215 | * makes the most sense but also requires applications to check | |
216 | * the value of the FillOrder tag; something they probabyl do | |
217 | * not do right now. | |
218 | * | |
219 | * The 'M' and 'm' flags are provided because some virtual memory | |
220 | * systems exhibit poor behaviour when large images are mapped. | |
221 | * These options permit clients to control the use of memory-mapped | |
222 | * files on a per-file basis. | |
223 | * | |
224 | * The 'C' and 'c' flags are provided because the library support | |
225 | * for chopping up large strips into multiple smaller strips is not | |
226 | * application-transparent and as such can cause problems. The 'c' | |
227 | * option permits applications that only want to look at the tags, | |
228 | * for example, to get the unadulterated TIFF tag information. | |
229 | */ | |
230 | for (cp = mode; *cp; cp++) | |
231 | switch (*cp) { | |
232 | case 'b': | |
233 | if ((m&O_CREAT) && !bigendian) | |
234 | tif->tif_flags |= TIFF_SWAB; | |
235 | break; | |
236 | case 'l': | |
237 | if ((m&O_CREAT) && bigendian) | |
238 | tif->tif_flags |= TIFF_SWAB; | |
239 | break; | |
240 | case 'B': | |
241 | tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | | |
242 | FILLORDER_MSB2LSB; | |
243 | break; | |
244 | case 'L': | |
245 | tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | | |
246 | FILLORDER_LSB2MSB; | |
247 | break; | |
248 | case 'H': | |
249 | tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | | |
250 | HOST_FILLORDER; | |
251 | break; | |
252 | case 'M': | |
253 | if (m == O_RDONLY) | |
254 | tif->tif_flags |= TIFF_MAPPED; | |
255 | break; | |
256 | case 'm': | |
257 | if (m == O_RDONLY) | |
258 | tif->tif_flags &= ~TIFF_MAPPED; | |
259 | break; | |
260 | case 'C': | |
261 | if (m == O_RDONLY) | |
262 | tif->tif_flags |= TIFF_STRIPCHOP; | |
263 | break; | |
264 | case 'c': | |
265 | if (m == O_RDONLY) | |
266 | tif->tif_flags &= ~TIFF_STRIPCHOP; | |
267 | break; | |
268 | } | |
269 | /* | |
270 | * Read in TIFF header. | |
271 | */ | |
272 | if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { | |
273 | if (tif->tif_mode == O_RDONLY) { | |
274 | TIFFError(name, "Cannot read TIFF header"); | |
275 | goto bad; | |
276 | } | |
277 | /* | |
278 | * Setup header and write. | |
279 | */ | |
280 | tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB | |
281 | ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN) | |
282 | : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN); | |
283 | tif->tif_header.tiff_version = TIFF_VERSION; | |
284 | if (tif->tif_flags & TIFF_SWAB) | |
285 | TIFFSwabShort(&tif->tif_header.tiff_version); | |
286 | tif->tif_header.tiff_diroff = 0; /* filled in later */ | |
287 | if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { | |
288 | TIFFError(name, "Error writing TIFF header"); | |
289 | goto bad; | |
290 | } | |
291 | /* | |
292 | * Setup the byte order handling. | |
293 | */ | |
294 | TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); | |
295 | /* | |
296 | * Setup default directory. | |
297 | */ | |
298 | if (!TIFFDefaultDirectory(tif)) | |
299 | goto bad; | |
300 | tif->tif_diroff = 0; | |
301 | return (tif); | |
302 | } | |
303 | /* | |
304 | * Setup the byte order handling. | |
305 | */ | |
306 | if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN && | |
307 | tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) { | |
308 | TIFFError(name, "Not a TIFF file, bad magic number %d (0x%x)", | |
309 | tif->tif_header.tiff_magic, | |
310 | tif->tif_header.tiff_magic); | |
311 | goto bad; | |
312 | } | |
313 | TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); | |
314 | /* | |
315 | * Swap header if required. | |
316 | */ | |
317 | if (tif->tif_flags & TIFF_SWAB) { | |
318 | TIFFSwabShort(&tif->tif_header.tiff_version); | |
319 | TIFFSwabLong(&tif->tif_header.tiff_diroff); | |
320 | } | |
321 | /* | |
322 | * Now check version (if needed, it's been byte-swapped). | |
323 | * Note that this isn't actually a version number, it's a | |
324 | * magic number that doesn't change (stupid). | |
325 | */ | |
326 | if (tif->tif_header.tiff_version != TIFF_VERSION) { | |
327 | TIFFError(name, | |
328 | "Not a TIFF file, bad version number %d (0x%x)", | |
329 | tif->tif_header.tiff_version, | |
330 | tif->tif_header.tiff_version); | |
331 | goto bad; | |
332 | } | |
333 | tif->tif_flags |= TIFF_MYBUFFER; | |
334 | tif->tif_rawcp = tif->tif_rawdata = 0; | |
335 | tif->tif_rawdatasize = 0; | |
336 | /* | |
337 | * Setup initial directory. | |
338 | */ | |
339 | switch (mode[0]) { | |
340 | case 'r': | |
341 | tif->tif_nextdiroff = tif->tif_header.tiff_diroff; | |
342 | /* | |
343 | * Try to use a memory-mapped file if the client | |
344 | * has not explicitly suppressed usage with the | |
345 | * 'm' flag in the open mode (see above). | |
346 | */ | |
347 | if ((tif->tif_flags & TIFF_MAPPED) && | |
348 | !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size)) | |
349 | tif->tif_flags &= ~TIFF_MAPPED; | |
350 | if (TIFFReadDirectory(tif)) { | |
351 | tif->tif_rawcc = -1; | |
352 | tif->tif_flags |= TIFF_BUFFERSETUP; | |
353 | return (tif); | |
354 | } | |
355 | break; | |
356 | case 'a': | |
357 | /* | |
358 | * New directories are automatically append | |
359 | * to the end of the directory chain when they | |
360 | * are written out (see TIFFWriteDirectory). | |
361 | */ | |
362 | if (!TIFFDefaultDirectory(tif)) | |
363 | goto bad; | |
364 | return (tif); | |
365 | } | |
366 | bad: | |
367 | tif->tif_mode = O_RDONLY; /* XXX avoid flush */ | |
368 | TIFFClose(tif); | |
369 | return ((TIFF*)0); | |
370 | bad2: | |
371 | (void) (*closeproc)(clientdata); | |
372 | return ((TIFF*)0); | |
373 | } | |
374 | ||
375 | /* | |
376 | * Query functions to access private data. | |
377 | */ | |
378 | ||
379 | /* | |
380 | * Return open file's name. | |
381 | */ | |
382 | const char * | |
383 | TIFFFileName(TIFF* tif) | |
384 | { | |
385 | return (tif->tif_name); | |
386 | } | |
387 | ||
388 | /* | |
389 | * Return open file's I/O descriptor. | |
390 | */ | |
391 | int | |
392 | TIFFFileno(TIFF* tif) | |
393 | { | |
394 | return (tif->tif_fd); | |
395 | } | |
396 | ||
397 | /* | |
398 | * Return read/write mode. | |
399 | */ | |
400 | int | |
401 | TIFFGetMode(TIFF* tif) | |
402 | { | |
403 | return (tif->tif_mode); | |
404 | } | |
405 | ||
406 | /* | |
407 | * Return nonzero if file is organized in | |
408 | * tiles; zero if organized as strips. | |
409 | */ | |
410 | int | |
411 | TIFFIsTiled(TIFF* tif) | |
412 | { | |
413 | return (isTiled(tif)); | |
414 | } | |
415 | ||
416 | /* | |
417 | * Return current row being read/written. | |
418 | */ | |
419 | uint32 | |
420 | TIFFCurrentRow(TIFF* tif) | |
421 | { | |
422 | return (tif->tif_row); | |
423 | } | |
424 | ||
425 | /* | |
426 | * Return index of the current directory. | |
427 | */ | |
428 | tdir_t | |
429 | TIFFCurrentDirectory(TIFF* tif) | |
430 | { | |
431 | return (tif->tif_curdir); | |
432 | } | |
433 | ||
434 | /* | |
435 | * Return current strip. | |
436 | */ | |
437 | tstrip_t | |
438 | TIFFCurrentStrip(TIFF* tif) | |
439 | { | |
440 | return (tif->tif_curstrip); | |
441 | } | |
442 | ||
443 | /* | |
444 | * Return current tile. | |
445 | */ | |
446 | ttile_t | |
447 | TIFFCurrentTile(TIFF* tif) | |
448 | { | |
449 | return (tif->tif_curtile); | |
450 | } | |
451 | ||
452 | /* | |
453 | * Return nonzero if the file has byte-swapped data. | |
454 | */ | |
455 | int | |
456 | TIFFIsByteSwapped(TIFF* tif) | |
457 | { | |
458 | return ((tif->tif_flags & TIFF_SWAB) != 0); | |
459 | } | |
460 | ||
461 | /* | |
462 | * Return nonzero if the data is returned up-sampled. | |
463 | */ | |
464 | int | |
465 | TIFFIsUpSampled(TIFF* tif) | |
466 | { | |
467 | return (isUpSampled(tif)); | |
468 | } | |
469 | ||
470 | /* | |
471 | * Return nonzero if the data is returned in MSB-to-LSB bit order. | |
472 | */ | |
473 | int | |
474 | TIFFIsMSB2LSB(TIFF* tif) | |
475 | { | |
476 | return (isFillOrder(tif, FILLORDER_MSB2LSB)); | |
477 | } |