home *** CD-ROM | disk | FTP | other *** search
- /* $Header: /usr/people/sam/tiff/libtiff/RCS/tif_open.c,v 1.59 1995/07/20 16:38:53 sam Exp $ */
-
- /*
- * Copyright (c) 1988-1995 Sam Leffler
- * Copyright (c) 1991-1995 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
- * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
- /*
- * TIFF Library.
- */
- #include "tiffiop.h"
-
- static const long typemask[13] = {
- 0L, /* TIFF_NOTYPE */
- 0x000000ffL, /* TIFF_BYTE */
- 0xffffffffL, /* TIFF_ASCII */
- 0x0000ffffL, /* TIFF_SHORT */
- 0xffffffffL, /* TIFF_LONG */
- 0xffffffffL, /* TIFF_RATIONAL */
- 0x000000ffL, /* TIFF_SBYTE */
- 0x000000ffL, /* TIFF_UNDEFINED */
- 0x0000ffffL, /* TIFF_SSHORT */
- 0xffffffffL, /* TIFF_SLONG */
- 0xffffffffL, /* TIFF_SRATIONAL */
- 0xffffffffL, /* TIFF_FLOAT */
- 0xffffffffL, /* TIFF_DOUBLE */
- };
- static const int bigTypeshift[13] = {
- 0, /* TIFF_NOTYPE */
- 24, /* TIFF_BYTE */
- 0, /* TIFF_ASCII */
- 16, /* TIFF_SHORT */
- 0, /* TIFF_LONG */
- 0, /* TIFF_RATIONAL */
- 24, /* TIFF_SBYTE */
- 24, /* TIFF_UNDEFINED */
- 16, /* TIFF_SSHORT */
- 0, /* TIFF_SLONG */
- 0, /* TIFF_SRATIONAL */
- 0, /* TIFF_FLOAT */
- 0, /* TIFF_DOUBLE */
- };
- static const int litTypeshift[13] = {
- 0, /* TIFF_NOTYPE */
- 0, /* TIFF_BYTE */
- 0, /* TIFF_ASCII */
- 0, /* TIFF_SHORT */
- 0, /* TIFF_LONG */
- 0, /* TIFF_RATIONAL */
- 0, /* TIFF_SBYTE */
- 0, /* TIFF_UNDEFINED */
- 0, /* TIFF_SSHORT */
- 0, /* TIFF_SLONG */
- 0, /* TIFF_SRATIONAL */
- 0, /* TIFF_FLOAT */
- 0, /* TIFF_DOUBLE */
- };
-
- /*
- * Initialize the bit fill order, the
- * shift & mask tables, and the byte
- * swapping state according to the file
- * contents and the machine architecture.
- */
- static void
- TIFFInitOrder(register TIFF* tif, int magic, int bigendian)
- {
- #ifdef notdef
- /*
- * NB: too many applications assume that data is returned
- * by the library in MSB2LSB bit order to change the
- * default bit order to reflect the native cpu. This
- * may change in the future in which case applications
- * will need to check the value of the FillOrder tag.
- */
- tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | HOST_FILLORDER;
- #else
- tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_MSB2LSB;
- #endif
-
- tif->tif_typemask = typemask;
- if (magic == TIFF_BIGENDIAN) {
- tif->tif_typeshift = bigTypeshift;
- if (!bigendian)
- tif->tif_flags |= TIFF_SWAB;
- } else {
- tif->tif_typeshift = litTypeshift;
- if (bigendian)
- tif->tif_flags |= TIFF_SWAB;
- }
- }
-
- int
- _TIFFgetMode(const char* mode, const char* module)
- {
- int m = -1;
-
- switch (mode[0]) {
- case 'r':
- m = O_RDONLY;
- if (mode[1] == '+')
- m = O_RDWR;
- break;
- case 'w':
- case 'a':
- m = O_RDWR|O_CREAT;
- if (mode[0] == 'w')
- m |= O_TRUNC;
- break;
- default:
- TIFFError(module, "\"%s\": Bad mode", mode);
- break;
- }
- return (m);
- }
-
- 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
- )
- {
- static const char module[] = "TIFFClientOpen";
- TIFF *tif;
- int m, bigendian;
-
- m = _TIFFgetMode(mode, module);
- if (m == -1)
- goto bad2;
- tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
- if (tif == NULL) {
- TIFFError(module, "%s: Out of memory (TIFF structure)", name);
- goto bad2;
- }
- _TIFFmemset(tif, 0, sizeof (*tif));
- tif->tif_name = (char *)tif + sizeof (TIFF);
- strcpy(tif->tif_name, name);
- tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
- tif->tif_curdir = (tdir_t) -1; /* non-existent directory */
- tif->tif_curoff = 0;
- tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */
- tif->tif_row = (uint32)-1; /* read/write pre-increment */
- tif->tif_clientdata = clientdata;
- tif->tif_readproc = readproc;
- tif->tif_writeproc = writeproc;
- tif->tif_seekproc = seekproc;
- tif->tif_closeproc = closeproc;
- tif->tif_sizeproc = sizeproc;
- tif->tif_mapproc = mapproc;
- tif->tif_unmapproc = unmapproc;
-
- { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; }
- #ifdef ENDIANHACK_SUPPORT
- /*
- * Numerous vendors, typically on the PC, do not correctly
- * support TIFF; they only support the Intel little-endian
- * byte order. If this hack is enabled, then applications
- * can open a file with a specific byte-order by specifying
- * either "wl" (for litt-endian byte order) or "wb" for
- * (big-endian byte order). This support is not configured
- * by default because it supports the violation of the TIFF
- * spec that says that readers *MUST* support both byte orders.
- *
- * It is strongly recommended that you not use this feature
- * except to deal with busted apps that write invalid TIFF.
- * And even in those cases you should bang on the vendors to
- * fix their software.
- */
- if ((m&O_CREAT) &&
- ((bigendian && mode[1] == 'l') || (!bigendian && mode[1] == 'b')))
- tif->tif_flags |= TIFF_SWAB;
- #endif
- /*
- * Read in TIFF header.
- */
- if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
- if (tif->tif_mode == O_RDONLY) {
- TIFFError(name, "Cannot read TIFF header");
- goto bad;
- }
- /*
- * Setup header and write.
- */
- tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
- ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN)
- : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN);
- tif->tif_header.tiff_version = TIFF_VERSION;
- tif->tif_header.tiff_diroff = 0; /* filled in later */
- if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
- TIFFError(name, "Error writing TIFF header");
- goto bad;
- }
- /*
- * Setup the byte order handling.
- */
- TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
- /*
- * Setup default directory.
- */
- if (!TIFFDefaultDirectory(tif))
- goto bad;
- tif->tif_diroff = 0;
- return (tif);
- }
- /*
- * Setup the byte order handling.
- */
- if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
- tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) {
- TIFFError(name, "Not a TIFF file, bad magic number %d (0x%x)",
- tif->tif_header.tiff_magic,
- tif->tif_header.tiff_magic);
- goto bad;
- }
- TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian);
- /*
- * Swap header if required.
- */
- if (tif->tif_flags & TIFF_SWAB) {
- TIFFSwabShort(&tif->tif_header.tiff_version);
- TIFFSwabLong(&tif->tif_header.tiff_diroff);
- }
- /*
- * Now check version (if needed, it's been byte-swapped).
- * Note that this isn't actually a version number, it's a
- * magic number that doesn't change (stupid).
- */
- if (tif->tif_header.tiff_version != TIFF_VERSION) {
- TIFFError(name,
- "Not a TIFF file, bad version number %d (0x%x)",
- tif->tif_header.tiff_version,
- tif->tif_header.tiff_version);
- goto bad;
- }
- tif->tif_flags |= TIFF_MYBUFFER;
- tif->tif_rawcp = tif->tif_rawdata = 0;
- tif->tif_rawdatasize = 0;
- /*
- * Setup initial directory.
- */
- switch (mode[0]) {
- case 'r':
- tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
- if (TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
- tif->tif_flags |= TIFF_MAPPED;
- if (TIFFReadDirectory(tif)) {
- tif->tif_rawcc = -1;
- tif->tif_flags |= TIFF_BUFFERSETUP;
- return (tif);
- }
- break;
- case 'a':
- /*
- * New directories are automatically append
- * to the end of the directory chain when they
- * are written out (see TIFFWriteDirectory).
- */
- if (!TIFFDefaultDirectory(tif))
- goto bad;
- return (tif);
- }
- bad:
- tif->tif_mode = O_RDONLY; /* XXX avoid flush */
- TIFFClose(tif);
- return ((TIFF*)0);
- bad2:
- (void) (*closeproc)(clientdata);
- return ((TIFF*)0);
- }
-
- /*
- * Query functions to access private data.
- */
-
- /*
- * Return open file's name.
- */
- const char *
- TIFFFileName(TIFF* tif)
- {
- return (tif->tif_name);
- }
-
- /*
- * Return open file's I/O descriptor.
- */
- int
- TIFFFileno(TIFF* tif)
- {
- return (tif->tif_fd);
- }
-
- /*
- * Return read/write mode.
- */
- int
- TIFFGetMode(TIFF* tif)
- {
- return (tif->tif_mode);
- }
-
- /*
- * Return nonzero if file is organized in
- * tiles; zero if organized as strips.
- */
- int
- TIFFIsTiled(TIFF* tif)
- {
- return (isTiled(tif));
- }
-
- /*
- * Return current row being read/written.
- */
- uint32
- TIFFCurrentRow(TIFF* tif)
- {
- return (tif->tif_row);
- }
-
- /*
- * Return index of the current directory.
- */
- tdir_t
- TIFFCurrentDirectory(TIFF* tif)
- {
- return (tif->tif_curdir);
- }
-
- /*
- * Return current strip.
- */
- tstrip_t
- TIFFCurrentStrip(TIFF* tif)
- {
- return (tif->tif_curstrip);
- }
-
- /*
- * Return current tile.
- */
- ttile_t
- TIFFCurrentTile(TIFF* tif)
- {
- return (tif->tif_curtile);
- }
-
- /*
- * Return nonzero if the file has byte-swapped data.
- */
- int
- TIFFIsByteSwapped(TIFF* tif)
- {
- return ((tif->tif_flags & TIFF_SWAB) != 0);
- }
-
- /*
- * Return nonzero if the data is returned up-sampled.
- */
- int
- TIFFIsUpSampled(TIFF* tif)
- {
- return (isUpSampled(tif));
- }
-
- /*
- * Return nonzero if the data is returned in MSB-to-LSB bit order.
- */
- int
- TIFFIsMSB2LSB(TIFF* tif)
- {
- return (isFillOrder(tif, FILLORDER_MSB2LSB));
- }
-