1 /*
2 * Copyright (c) 1988-1997 Sam Leffler
3 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10 * publicity relating to the software without the specific, prior written
11 * permission of Sam Leffler and Silicon Graphics.
12 *
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25 /*
26 * TIFF Library.
27 */
28 #include "tiffiop.h"
29
30 /*
31 * Dummy functions to fill the omitted client procedures.
32 */
33 static int
_tiffDummyMapProc(thandle_t fd,void ** pbase,toff_t * psize)34 _tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize)
35 {
36 (void) fd; (void) pbase; (void) psize;
37 return (0);
38 }
39
40 static void
_tiffDummyUnmapProc(thandle_t fd,void * base,toff_t size)41 _tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size)
42 {
43 (void) fd; (void) base; (void) size;
44 }
45
46 int
_TIFFgetMode(const char * mode,const char * module)47 _TIFFgetMode(const char* mode, const char* module)
48 {
49 int m = -1;
50
51 switch (mode[0]) {
52 case 'r':
53 m = O_RDONLY;
54 if (mode[1] == '+')
55 m = O_RDWR;
56 break;
57 case 'w':
58 case 'a':
59 m = O_RDWR|O_CREAT;
60 if (mode[0] == 'w')
61 m |= O_TRUNC;
62 break;
63 default:
64 TIFFErrorExt(0, module, "\"%s\": Bad mode", mode);
65 break;
66 }
67 return (m);
68 }
69
70 TIFF*
TIFFClientOpen(const char * name,const char * mode,thandle_t clientdata,TIFFReadWriteProc readproc,TIFFReadWriteProc writeproc,TIFFSeekProc seekproc,TIFFCloseProc closeproc,TIFFSizeProc sizeproc,TIFFMapFileProc mapproc,TIFFUnmapFileProc unmapproc)71 TIFFClientOpen(
72 const char* name, const char* mode,
73 thandle_t clientdata,
74 TIFFReadWriteProc readproc,
75 TIFFReadWriteProc writeproc,
76 TIFFSeekProc seekproc,
77 TIFFCloseProc closeproc,
78 TIFFSizeProc sizeproc,
79 TIFFMapFileProc mapproc,
80 TIFFUnmapFileProc unmapproc
81 )
82 {
83 static const char module[] = "TIFFClientOpen";
84 TIFF *tif;
85 int m;
86 const char* cp;
87
88 /* The following are configuration checks. They should be redundant, but should not
89 * compile to any actual code in an optimised release build anyway. If any of them
90 * fail, (makefile-based or other) configuration is not correct */
91 assert(sizeof(uint8)==1);
92 assert(sizeof(int8)==1);
93 assert(sizeof(uint16)==2);
94 assert(sizeof(int16)==2);
95 assert(sizeof(uint32)==4);
96 assert(sizeof(int32)==4);
97 assert(sizeof(uint64)==8);
98 assert(sizeof(int64)==8);
99 assert(sizeof(tmsize_t)==sizeof(void*));
100 {
101 union{
102 uint8 a8[2];
103 uint16 a16;
104 } n;
105 n.a8[0]=1;
106 n.a8[1]=0;
107 #ifdef WORDS_BIGENDIAN
108 assert(n.a16==256);
109 #else
110 assert(n.a16==1);
111 #endif
112 }
113
114 m = _TIFFgetMode(mode, module);
115 if (m == -1)
116 goto bad2;
117 tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1));
118 if (tif == NULL) {
119 TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
120 goto bad2;
121 }
122 _TIFFmemset(tif, 0, sizeof (*tif));
123 tif->tif_name = (char *)tif + sizeof (TIFF);
124 strcpy(tif->tif_name, name);
125 tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
126 tif->tif_curdir = (uint16) -1; /* non-existent directory */
127 tif->tif_curoff = 0;
128 tif->tif_curstrip = (uint32) -1; /* invalid strip */
129 tif->tif_row = (uint32) -1; /* read/write pre-increment */
130 tif->tif_clientdata = clientdata;
131 if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
132 TIFFErrorExt(clientdata, module,
133 "One of the client procedures is NULL pointer.");
134 goto bad2;
135 }
136 tif->tif_readproc = readproc;
137 tif->tif_writeproc = writeproc;
138 tif->tif_seekproc = seekproc;
139 tif->tif_closeproc = closeproc;
140 tif->tif_sizeproc = sizeproc;
141 if (mapproc)
142 tif->tif_mapproc = mapproc;
143 else
144 tif->tif_mapproc = _tiffDummyMapProc;
145 if (unmapproc)
146 tif->tif_unmapproc = unmapproc;
147 else
148 tif->tif_unmapproc = _tiffDummyUnmapProc;
149 _TIFFSetDefaultCompressionState(tif); /* setup default state */
150 /*
151 * Default is to return data MSB2LSB and enable the
152 * use of memory-mapped files and strip chopping when
153 * a file is opened read-only.
154 */
155 tif->tif_flags = FILLORDER_MSB2LSB;
156 if (m == O_RDONLY )
157 tif->tif_flags |= TIFF_MAPPED;
158
159 #ifdef STRIPCHOP_DEFAULT
160 if (m == O_RDONLY || m == O_RDWR)
161 tif->tif_flags |= STRIPCHOP_DEFAULT;
162 #endif
163
164 /*
165 * Process library-specific flags in the open mode string.
166 * The following flags may be used to control intrinsic library
167 * behaviour that may or may not be desirable (usually for
168 * compatibility with some application that claims to support
169 * TIFF but only supports some brain dead idea of what the
170 * vendor thinks TIFF is):
171 *
172 * 'l' use little-endian byte order for creating a file
173 * 'b' use big-endian byte order for creating a file
174 * 'L' read/write information using LSB2MSB bit order
175 * 'B' read/write information using MSB2LSB bit order
176 * 'H' read/write information using host bit order
177 * 'M' enable use of memory-mapped files when supported
178 * 'm' disable use of memory-mapped files
179 * 'C' enable strip chopping support when reading
180 * 'c' disable strip chopping support
181 * 'h' read TIFF header only, do not load the first IFD
182 * '4' ClassicTIFF for creating a file (default)
183 * '8' BigTIFF for creating a file
184 *
185 * The use of the 'l' and 'b' flags is strongly discouraged.
186 * These flags are provided solely because numerous vendors,
187 * typically on the PC, do not correctly support TIFF; they
188 * only support the Intel little-endian byte order. This
189 * support is not configured by default because it supports
190 * the violation of the TIFF spec that says that readers *MUST*
191 * support both byte orders. It is strongly recommended that
192 * you not use this feature except to deal with busted apps
193 * that write invalid TIFF. And even in those cases you should
194 * bang on the vendors to fix their software.
195 *
196 * The 'L', 'B', and 'H' flags are intended for applications
197 * that can optimize operations on data by using a particular
198 * bit order. By default the library returns data in MSB2LSB
199 * bit order for compatibility with older versions of this
200 * library. Returning data in the bit order of the native CPU
201 * makes the most sense but also requires applications to check
202 * the value of the FillOrder tag; something they probably do
203 * not do right now.
204 *
205 * The 'M' and 'm' flags are provided because some virtual memory
206 * systems exhibit poor behaviour when large images are mapped.
207 * These options permit clients to control the use of memory-mapped
208 * files on a per-file basis.
209 *
210 * The 'C' and 'c' flags are provided because the library support
211 * for chopping up large strips into multiple smaller strips is not
212 * application-transparent and as such can cause problems. The 'c'
213 * option permits applications that only want to look at the tags,
214 * for example, to get the unadulterated TIFF tag information.
215 */
216 for (cp = mode; *cp; cp++)
217 switch (*cp) {
218 case 'b':
219 #ifndef WORDS_BIGENDIAN
220 if (m&O_CREAT)
221 tif->tif_flags |= TIFF_SWAB;
222 #endif
223 break;
224 case 'l':
225 #ifdef WORDS_BIGENDIAN
226 if ((m&O_CREAT))
227 tif->tif_flags |= TIFF_SWAB;
228 #endif
229 break;
230 case 'B':
231 tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
232 FILLORDER_MSB2LSB;
233 break;
234 case 'L':
235 tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
236 FILLORDER_LSB2MSB;
237 break;
238 case 'H':
239 tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
240 HOST_FILLORDER;
241 break;
242 case 'M':
243 if (m == O_RDONLY)
244 tif->tif_flags |= TIFF_MAPPED;
245 break;
246 case 'm':
247 if (m == O_RDONLY)
248 tif->tif_flags &= ~TIFF_MAPPED;
249 break;
250 case 'C':
251 if (m == O_RDONLY)
252 tif->tif_flags |= TIFF_STRIPCHOP;
253 break;
254 case 'c':
255 if (m == O_RDONLY)
256 tif->tif_flags &= ~TIFF_STRIPCHOP;
257 break;
258 case 'h':
259 tif->tif_flags |= TIFF_HEADERONLY;
260 break;
261 case '8':
262 if (m&O_CREAT)
263 tif->tif_flags |= TIFF_BIGTIFF;
264 break;
265 }
266 /*
267 * Read in TIFF header.
268 */
269 if ((m & O_TRUNC) ||
270 !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) {
271 if (tif->tif_mode == O_RDONLY) {
272 TIFFErrorExt(tif->tif_clientdata, name,
273 "Cannot read TIFF header");
274 goto bad;
275 }
276 /*
277 * Setup header and write.
278 */
279 #ifdef WORDS_BIGENDIAN
280 tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
281 ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
282 #else
283 tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
284 ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
285 #endif
286 if (!(tif->tif_flags&TIFF_BIGTIFF))
287 {
288 tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
289 tif->tif_header.classic.tiff_diroff = 0;
290 if (tif->tif_flags & TIFF_SWAB)
291 TIFFSwabShort(&tif->tif_header.common.tiff_version);
292 tif->tif_header_size = sizeof(TIFFHeaderClassic);
293 }
294 else
295 {
296 tif->tif_header.common.tiff_version = TIFF_VERSION_BIG;
297 tif->tif_header.big.tiff_offsetsize = 8;
298 tif->tif_header.big.tiff_unused = 0;
299 tif->tif_header.big.tiff_diroff = 0;
300 if (tif->tif_flags & TIFF_SWAB)
301 {
302 TIFFSwabShort(&tif->tif_header.common.tiff_version);
303 TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
304 }
305 tif->tif_header_size = sizeof (TIFFHeaderBig);
306 }
307 /*
308 * The doc for "fopen" for some STD_C_LIBs says that if you
309 * open a file for modify ("+"), then you must fseek (or
310 * fflush?) between any freads and fwrites. This is not
311 * necessary on most systems, but has been shown to be needed
312 * on Solaris.
313 */
314 TIFFSeekFile( tif, 0, SEEK_SET );
315 if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) {
316 TIFFErrorExt(tif->tif_clientdata, name,
317 "Error writing TIFF header");
318 goto bad;
319 }
320 /*
321 * Setup the byte order handling.
322 */
323 if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
324 #ifndef WORDS_BIGENDIAN
325 tif->tif_flags |= TIFF_SWAB;
326 #endif
327 } else {
328 #ifdef WORDS_BIGENDIAN
329 tif->tif_flags |= TIFF_SWAB;
330 #endif
331 }
332 /*
333 * Setup default directory.
334 */
335 if (!TIFFDefaultDirectory(tif))
336 goto bad;
337 tif->tif_diroff = 0;
338 tif->tif_dirlist = NULL;
339 tif->tif_dirlistsize = 0;
340 tif->tif_dirnumber = 0;
341 return (tif);
342 }
343 /*
344 * Setup the byte order handling.
345 */
346 if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
347 tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
348 #if MDI_SUPPORT
349 &&
350 #if HOST_BIGENDIAN
351 tif->tif_header.common.tiff_magic != MDI_BIGENDIAN
352 #else
353 tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN
354 #endif
355 ) {
356 TIFFErrorExt(tif->tif_clientdata, name,
357 "Not a TIFF or MDI file, bad magic number %d (0x%x)",
358 #else
359 ) {
360 TIFFErrorExt(tif->tif_clientdata, name,
361 "Not a TIFF file, bad magic number %d (0x%x)",
362 #endif
363 tif->tif_header.common.tiff_magic,
364 tif->tif_header.common.tiff_magic);
365 goto bad;
366 }
367 if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
368 #ifndef WORDS_BIGENDIAN
369 tif->tif_flags |= TIFF_SWAB;
370 #endif
371 } else {
372 #ifdef WORDS_BIGENDIAN
373 tif->tif_flags |= TIFF_SWAB;
374 #endif
375 }
376 if (tif->tif_flags & TIFF_SWAB)
377 TIFFSwabShort(&tif->tif_header.common.tiff_version);
378 if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&&
379 (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) {
380 TIFFErrorExt(tif->tif_clientdata, name,
381 "Not a TIFF file, bad version number %d (0x%x)",
382 tif->tif_header.common.tiff_version,
383 tif->tif_header.common.tiff_version);
384 goto bad;
385 }
386 if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC)
387 {
388 if (tif->tif_flags & TIFF_SWAB)
389 TIFFSwabLong(&tif->tif_header.classic.tiff_diroff);
390 tif->tif_header_size = sizeof(TIFFHeaderClassic);
391 }
392 else
393 {
394 if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic))))
395 {
396 TIFFErrorExt(tif->tif_clientdata, name,
397 "Cannot read TIFF header");
398 goto bad;
399 }
400 if (tif->tif_flags & TIFF_SWAB)
401 {
402 TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
403 TIFFSwabLong8(&tif->tif_header.big.tiff_diroff);
404 }
405 if (tif->tif_header.big.tiff_offsetsize != 8)
406 {
407 TIFFErrorExt(tif->tif_clientdata, name,
408 "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)",
409 tif->tif_header.big.tiff_offsetsize,
410 tif->tif_header.big.tiff_offsetsize);
411 goto bad;
412 }
413 if (tif->tif_header.big.tiff_unused != 0)
414 {
415 TIFFErrorExt(tif->tif_clientdata, name,
416 "Not a TIFF file, bad BigTIFF unused %d (0x%x)",
417 tif->tif_header.big.tiff_unused,
418 tif->tif_header.big.tiff_unused);
419 goto bad;
420 }
421 tif->tif_header_size = sizeof(TIFFHeaderBig);
422 tif->tif_flags |= TIFF_BIGTIFF;
423 }
424 tif->tif_flags |= TIFF_MYBUFFER;
425 tif->tif_rawcp = tif->tif_rawdata = 0;
426 tif->tif_rawdatasize = 0;
427 tif->tif_rawdataoff = 0;
428 tif->tif_rawdataloaded = 0;
429
430 switch (mode[0]) {
431 case 'r':
432 if (!(tif->tif_flags&TIFF_BIGTIFF))
433 tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff;
434 else
435 tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff;
436 /*
437 * Try to use a memory-mapped file if the client
438 * has not explicitly suppressed usage with the
439 * 'm' flag in the open mode (see above).
440 */
441 if (tif->tif_flags & TIFF_MAPPED)
442 {
443 toff_t n;
444 if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n))
445 {
446 tif->tif_size=(tmsize_t)n;
447 assert((toff_t)tif->tif_size==n);
448 }
449 else
450 tif->tif_flags &= ~TIFF_MAPPED;
451 }
452 /*
453 * Sometimes we do not want to read the first directory (for example,
454 * it may be broken) and want to proceed to other directories. I this
455 * case we use the TIFF_HEADERONLY flag to open file and return
456 * immediately after reading TIFF header.
457 */
458 if (tif->tif_flags & TIFF_HEADERONLY)
459 return (tif);
460
461 /*
462 * Setup initial directory.
463 */
464 if (TIFFReadDirectory(tif)) {
465 tif->tif_rawcc = (tmsize_t)-1;
466 tif->tif_flags |= TIFF_BUFFERSETUP;
467 return (tif);
468 }
469 break;
470 case 'a':
471 /*
472 * New directories are automatically append
473 * to the end of the directory chain when they
474 * are written out (see TIFFWriteDirectory).
475 */
476 if (!TIFFDefaultDirectory(tif))
477 goto bad;
478 return (tif);
479 }
480 bad:
481 tif->tif_mode = O_RDONLY; /* XXX avoid flush */
482 TIFFCleanup(tif);
483 bad2:
484 return ((TIFF*)0);
485 }
486
487 /*
488 * Query functions to access private data.
489 */
490
491 /*
492 * Return open file's name.
493 */
494 const char *
495 TIFFFileName(TIFF* tif)
496 {
497 return (tif->tif_name);
498 }
499
500 /*
501 * Set the file name.
502 */
503 const char *
504 TIFFSetFileName(TIFF* tif, const char *name)
505 {
506 const char* old_name = tif->tif_name;
507 tif->tif_name = (char *)name;
508 return (old_name);
509 }
510
511 /*
512 * Return open file's I/O descriptor.
513 */
514 int
515 TIFFFileno(TIFF* tif)
516 {
517 return (tif->tif_fd);
518 }
519
520 /*
521 * Set open file's I/O descriptor, and return previous value.
522 */
523 int
524 TIFFSetFileno(TIFF* tif, int fd)
525 {
526 int old_fd = tif->tif_fd;
527 tif->tif_fd = fd;
528 return old_fd;
529 }
530
531 /*
532 * Return open file's clientdata.
533 */
534 thandle_t
535 TIFFClientdata(TIFF* tif)
536 {
537 return (tif->tif_clientdata);
538 }
539
540 /*
541 * Set open file's clientdata, and return previous value.
542 */
543 thandle_t
544 TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
545 {
546 thandle_t m = tif->tif_clientdata;
547 tif->tif_clientdata = newvalue;
548 return m;
549 }
550
551 /*
552 * Return read/write mode.
553 */
554 int
555 TIFFGetMode(TIFF* tif)
556 {
557 return (tif->tif_mode);
558 }
559
560 /*
561 * Return read/write mode.
562 */
563 int
564 TIFFSetMode(TIFF* tif, int mode)
565 {
566 int old_mode = tif->tif_mode;
567 tif->tif_mode = mode;
568 return (old_mode);
569 }
570
571 /*
572 * Return nonzero if file is organized in
573 * tiles; zero if organized as strips.
574 */
575 int
576 TIFFIsTiled(TIFF* tif)
577 {
578 return (isTiled(tif));
579 }
580
581 /*
582 * Return current row being read/written.
583 */
584 uint32
585 TIFFCurrentRow(TIFF* tif)
586 {
587 return (tif->tif_row);
588 }
589
590 /*
591 * Return index of the current directory.
592 */
593 uint16
594 TIFFCurrentDirectory(TIFF* tif)
595 {
596 return (tif->tif_curdir);
597 }
598
599 /*
600 * Return current strip.
601 */
602 uint32
603 TIFFCurrentStrip(TIFF* tif)
604 {
605 return (tif->tif_curstrip);
606 }
607
608 /*
609 * Return current tile.
610 */
611 uint32
612 TIFFCurrentTile(TIFF* tif)
613 {
614 return (tif->tif_curtile);
615 }
616
617 /*
618 * Return nonzero if the file has byte-swapped data.
619 */
620 int
621 TIFFIsByteSwapped(TIFF* tif)
622 {
623 return ((tif->tif_flags & TIFF_SWAB) != 0);
624 }
625
626 /*
627 * Return nonzero if the data is returned up-sampled.
628 */
629 int
630 TIFFIsUpSampled(TIFF* tif)
631 {
632 return (isUpSampled(tif));
633 }
634
635 /*
636 * Return nonzero if the data is returned in MSB-to-LSB bit order.
637 */
638 int
639 TIFFIsMSB2LSB(TIFF* tif)
640 {
641 return (isFillOrder(tif, FILLORDER_MSB2LSB));
642 }
643
644 /*
645 * Return nonzero if given file was written in big-endian order.
646 */
647 int
648 TIFFIsBigEndian(TIFF* tif)
649 {
650 return (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN);
651 }
652
653 /*
654 * Return pointer to file read method.
655 */
656 TIFFReadWriteProc
657 TIFFGetReadProc(TIFF* tif)
658 {
659 return (tif->tif_readproc);
660 }
661
662 /*
663 * Return pointer to file write method.
664 */
665 TIFFReadWriteProc
666 TIFFGetWriteProc(TIFF* tif)
667 {
668 return (tif->tif_writeproc);
669 }
670
671 /*
672 * Return pointer to file seek method.
673 */
674 TIFFSeekProc
675 TIFFGetSeekProc(TIFF* tif)
676 {
677 return (tif->tif_seekproc);
678 }
679
680 /*
681 * Return pointer to file close method.
682 */
683 TIFFCloseProc
684 TIFFGetCloseProc(TIFF* tif)
685 {
686 return (tif->tif_closeproc);
687 }
688
689 /*
690 * Return pointer to file size requesting method.
691 */
692 TIFFSizeProc
693 TIFFGetSizeProc(TIFF* tif)
694 {
695 return (tif->tif_sizeproc);
696 }
697
698 /*
699 * Return pointer to memory mapping method.
700 */
701 TIFFMapFileProc
702 TIFFGetMapFileProc(TIFF* tif)
703 {
704 return (tif->tif_mapproc);
705 }
706
707 /*
708 * Return pointer to memory unmapping method.
709 */
710 TIFFUnmapFileProc
711 TIFFGetUnmapFileProc(TIFF* tif)
712 {
713 return (tif->tif_unmapproc);
714 }
715
716 /* vim: set ts=8 sts=8 sw=8 noet: */
717 /*
718 * Local Variables:
719 * mode: c
720 * c-basic-offset: 8
721 * fill-column: 78
722 * End:
723 */
724