mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-21 12:00:29 +02:00
392 lines
8.7 KiB
C
392 lines
8.7 KiB
C
#ifndef lint
|
|
static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_open.c,v 1.33 92/02/14 13:40:51 sam Exp $";
|
|
#endif
|
|
|
|
/*
|
|
* Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
|
|
* Copyright (c) 1991, 1992 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"
|
|
#include "prototypes.h"
|
|
|
|
#if USE_PROTOTYPES
|
|
extern int TIFFDefaultDirectory(TIFF*);
|
|
#else
|
|
extern int TIFFDefaultDirectory();
|
|
#endif
|
|
|
|
static long typemask[13] = {
|
|
0, /* TIFF_NOTYPE */
|
|
0x000000ff, /* TIFF_BYTE */
|
|
0xffffffff, /* TIFF_ASCII */
|
|
0x0000ffff, /* TIFF_SHORT */
|
|
0xffffffff, /* TIFF_LONG */
|
|
0xffffffff, /* TIFF_RATIONAL */
|
|
0x000000ff, /* TIFF_SBYTE */
|
|
0x000000ff, /* TIFF_UNDEFINED */
|
|
0x0000ffff, /* TIFF_SSHORT */
|
|
0xffffffff, /* TIFF_SLONG */
|
|
0xffffffff, /* TIFF_SRATIONAL */
|
|
0xffffffff, /* TIFF_FLOAT */
|
|
0xffffffff, /* TIFF_DOUBLE */
|
|
};
|
|
static int bigTypeshift[13] = {
|
|
0, /* TIFF_NOTYPE */
|
|
24, /* TIFF_BYTE */
|
|
0, /* TIFF_ASCII */
|
|
16, /* TIFF_SHORT */
|
|
0, /* TIFF_LONG */
|
|
0, /* TIFF_RATIONAL */
|
|
16, /* TIFF_SBYTE */
|
|
16, /* TIFF_UNDEFINED */
|
|
24, /* TIFF_SSHORT */
|
|
0, /* TIFF_SLONG */
|
|
0, /* TIFF_SRATIONAL */
|
|
0, /* TIFF_FLOAT */
|
|
0, /* TIFF_DOUBLE */
|
|
};
|
|
static 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
|
|
DECLARE3(TIFFInitOrder, register TIFF*, tif, int, magic, int, bigendian)
|
|
{
|
|
/* XXX how can we deduce this dynamically? */
|
|
tif->tif_fillorder = FILLORDER_MSB2LSB;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
static int
|
|
DECLARE2(getMode, char*, mode, 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);
|
|
}
|
|
|
|
/*
|
|
* Open a TIFF file for read/writing.
|
|
*/
|
|
TIFF *
|
|
TIFFOpen(name, mode)
|
|
char *name, *mode;
|
|
{
|
|
static char module[] = "TIFFOpen";
|
|
int m, fd;
|
|
|
|
m = getMode(mode, module);
|
|
if (m == -1)
|
|
return ((TIFF *)0);
|
|
fd = TIFFOpenFile(name, m|O_BINARY, 0666);
|
|
if (fd < 0) {
|
|
TIFFError(module, "%s: Cannot open", name);
|
|
return ((TIFF *)0);
|
|
}
|
|
return (TIFFFdOpen(fd, name, mode));
|
|
}
|
|
|
|
/*
|
|
* Open a TIFF file descriptor for read/writing.
|
|
*/
|
|
TIFF *
|
|
TIFFFdOpen(fd, name, mode)
|
|
int fd;
|
|
char *name, *mode;
|
|
{
|
|
static char module[] = "TIFFFdOpen";
|
|
TIFF *tif;
|
|
int m, bigendian;
|
|
|
|
m = getMode(mode, module);
|
|
if (m == -1)
|
|
goto bad2;
|
|
tif = (TIFF *)debug_malloc(sizeof (TIFF) + csstrlen(name) + 1, 0,
|
|
"c:\\halo\\SOURCE\\bitmaps\\libtiff\\tif_open.c", 171);
|
|
if (tif == NULL) {
|
|
TIFFError(module, "%s: Out of memory (TIFF structure)", name);
|
|
goto bad2;
|
|
}
|
|
csmemset((char *)tif, 0, sizeof (*tif));
|
|
tif->tif_name = (char *)tif + sizeof (TIFF);
|
|
csstrcpy(tif->tif_name, name);
|
|
tif->tif_fd = fd;
|
|
tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
|
|
tif->tif_curdir = -1; /* non-existent directory */
|
|
tif->tif_curoff = 0;
|
|
tif->tif_curstrip = -1; /* invalid strip */
|
|
tif->tif_row = -1; /* read/write pre-increment */
|
|
{ int one = 1; bigendian = (*(char *)&one == 0); }
|
|
/*
|
|
* Read in TIFF header.
|
|
*/
|
|
if (!ReadOK(fd, &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 = bigendian ?
|
|
TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
|
|
tif->tif_header.tiff_version = TIFF_VERSION;
|
|
tif->tif_header.tiff_diroff = 0; /* filled in later */
|
|
if (!WriteOK(fd, &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;
|
|
#ifdef MMAP_SUPPORT
|
|
if (TIFFMapFileContents(fd, &tif->tif_base, &tif->tif_size))
|
|
tif->tif_flags |= TIFF_MAPPED;
|
|
#endif
|
|
if (TIFFReadDirectory(tif)) {
|
|
tif->tif_rawcc = -1;
|
|
tif->tif_flags |= TIFF_BUFFERSETUP;
|
|
return (tif);
|
|
}
|
|
break;
|
|
case 'a':
|
|
/*
|
|
* Don't append to file that has information
|
|
* byte swapped -- we will write data that is
|
|
* in the opposite order.
|
|
*/
|
|
if (tif->tif_flags & TIFF_SWAB) {
|
|
TIFFError(name,
|
|
"Cannot append to file that has opposite byte ordering");
|
|
goto bad;
|
|
}
|
|
/*
|
|
* 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) close(fd);
|
|
return ((TIFF *)0);
|
|
}
|
|
|
|
TIFFScanlineSize(tif)
|
|
TIFF *tif;
|
|
{
|
|
TIFFDirectory *td = &tif->tif_dir;
|
|
long scanline;
|
|
|
|
scanline = td->td_bitspersample * td->td_imagewidth;
|
|
if (td->td_planarconfig == PLANARCONFIG_CONTIG)
|
|
scanline *= td->td_samplesperpixel;
|
|
return (howmany(scanline, 8));
|
|
}
|
|
|
|
/*
|
|
* Query functions to access private data.
|
|
*/
|
|
|
|
/*
|
|
* Return open file's name.
|
|
*/
|
|
char *
|
|
TIFFFileName(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (tif->tif_name);
|
|
}
|
|
|
|
/*
|
|
* Return open file's I/O descriptor.
|
|
*/
|
|
int
|
|
TIFFFileno(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (tif->tif_fd);
|
|
}
|
|
|
|
/*
|
|
* Return read/write mode.
|
|
*/
|
|
int
|
|
TIFFGetMode(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (tif->tif_mode);
|
|
}
|
|
|
|
/*
|
|
* Return nonzero if file is organized in
|
|
* tiles; zero if organized as strips.
|
|
*/
|
|
int
|
|
TIFFIsTiled(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (isTiled(tif));
|
|
}
|
|
|
|
/*
|
|
* Return current row being read/written.
|
|
*/
|
|
long
|
|
TIFFCurrentRow(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (tif->tif_row);
|
|
}
|
|
|
|
/*
|
|
* Return index of the current directory.
|
|
*/
|
|
int
|
|
TIFFCurrentDirectory(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (tif->tif_curdir);
|
|
}
|
|
|
|
/*
|
|
* Return current strip.
|
|
*/
|
|
int
|
|
TIFFCurrentStrip(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (tif->tif_curstrip);
|
|
}
|
|
|
|
/*
|
|
* Return current tile.
|
|
*/
|
|
int
|
|
TIFFCurrentTile(tif)
|
|
TIFF *tif;
|
|
{
|
|
return (tif->tif_curtile);
|
|
}
|