#pragma warn -use static char *sccsid = "@(#)TIFF/tif_open.c 1.19, Copyright (c) Sam Leffler, Dieter Linde, "__DATE__; #pragma warn .use /* * Copyright (c) 1988, 1990 by Sam Leffler, Nov 15 1990 * All rights reserved. * * This file is provided for unrestricted use provided that this legend is included on all tape media and as a part of the * software program in whole or part. Users may copy, modify or distribute this file at will. * * TIFF Library. */ #include #include "tiffio.h" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define ord(e) ((int)e) /**************************************************************************** * 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 ) { /*** XXX how can we deduce this dynamically? ***/ tif->tif_fillorder = FILLORDER_MSB2LSB; tif->tif_typemask[0] = 0; tif->tif_typemask[ord(TIFF_BYTE)] = 0xff; tif->tif_typemask[ord(TIFF_SHORT)] = 0xffff; tif->tif_typemask[ord(TIFF_LONG)] = 0xffffffffL; tif->tif_typemask[ord(TIFF_RATIONAL)] = 0xffffffffL; tif->tif_typeshift[0] = 0; tif->tif_typeshift[ord(TIFF_LONG)] = 0; tif->tif_typeshift[ord(TIFF_RATIONAL)] = 0; if (magic == TIFF_BIGENDIAN) { tif->tif_typeshift[ord(TIFF_BYTE)] = 24; tif->tif_typeshift[ord(TIFF_SHORT)] = 16; if (!bigendian) tif->tif_flags |= TIFF_SWAB; } else { tif->tif_typeshift[ord(TIFF_BYTE)] = 0; tif->tif_typeshift[ord(TIFF_SHORT)] = 0; if (bigendian) tif->tif_flags |= TIFF_SWAB; } } /**************************************************************************** * */ static int 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, "bad mode '%s'", mode); break; } return(m); } /**************************************************************************** * Open a TIFF file descriptor for read/writing. */ TIFF * TIFFFdOpen( int fd, char *name, char *mode ) { static char *module = "TIFFFdOpen"; TIFF *tif; int m, bigendian; if ((m = getMode(mode, module)) == -1) goto bad2; if ((tif = (TIFF *)malloc(sizeof(TIFF) + strlen(name) + 1)) == NULL) { TIFFError(module, "out of memory allocating TIFF structure"); goto bad2; } bzero(tif, sizeof(*tif)); tif->tif_name = (char *)tif + sizeof(TIFF); strcpy(tif->tif_name, name); tif->tif_fd = fd; tif->tif_mode = m & ~(O_CREAT | O_TRUNC); tif->tif_curoff = 0; tif->tif_curstrip = -1; /* invalid strip */ tif->tif_row = -1; /* read/write pre-increment */ bigendian = TRUE; /* * Read in TIFF header. */ if (!ReadOK(fd, &tif->tif_header, sizeof(TIFFHeader))) { if (tif->tif_mode == O_RDONLY) { TIFFError(module, "can't 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(module, "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(module, "\"%s\" isn't a TIFF file, bad magic number 0x%04x", name, 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(module, "\"%s\" isn't a TIFF file, bad version number 0x%04x", name, tif->tif_header.tiff_version); goto bad; } /* * Setup initial directory. */ switch (mode[0]) { case 'r': tif->tif_nextdiroff = tif->tif_header.tiff_diroff; 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(module, "can't append to a 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(NULL); bad2: close(fd); return(NULL); } /**************************************************************************** * Open a TIFF file for read/writing. */ TIFF * TIFFOpen( char *name, char *mode ) { static char *module = "TIFFOpen"; int m, fd; m = getMode(mode, module); if (m == -1) return(NULL); if ((fd = TIFFOpenFile(name, m, 0666)) < 0) { TIFFError(module, "can't open file \"%s\"", name); return(NULL); } return(TIFFFdOpen(fd, name, mode)); } /**************************************************************************** * */ int TIFFScanlineSize( 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; #define howmany(x, y) (((x) + ((y) - 1)) / (y)) return((int)howmany(scanline, 8)); }