/src/FreeImage/Source/LibTIFF/tif_open.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 695 lines · 429 code · 43 blank · 223 comment · 60 complexity · 21a690711a7977752408462dc118e486 MD5 · raw file

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