/** ** $Header: /roq/libim/imiff.c 1 11/02/99 4:38p Zaphod $ ** Copyright (c) 1989-1995 San Diego Supercomputer Center (SDSC) ** a division of General Atomics, San Diego, California, USA ** ** Users and possessors of this source code are hereby granted a ** nonexclusive, royalty-free copyright and design patent license to ** use this code in individual software. License is not granted for ** commercial resale, in whole or in part, without prior written ** permission from SDSC. This source is provided "AS IS" without express ** or implied warranty of any kind. ** ** For further information contact: ** E-Mail: info@sds.sdsc.edu ** ** Surface Mail: Information Center ** San Diego Supercomputer Center ** P.O. Box 85608 ** San Diego, CA 92138-5608 ** (619) 534-5000 **/ #define HEADER " $Header: /roq/libim/imiff.c 1 11/02/99 4:38p Zaphod $" /** ** FILE ** imiff.c - Sun TAAC file format I/O ** ** PROJECT ** libim - SDSC image manipulation library ** ** DESCRIPTION ** imiff.c contains routines to read and write Sun TAAC IFF files for ** the image manipulation library. Raster data read in is stored ** in a VFB and optional CLT in a tag list. Raster data written ** out is taken from a tag list. ** ** PUBLIC CONTENTS ** d =defined constant ** f =function ** m =defined macro ** t =typedef/struct/union ** v =variable ** ? =other ** ** none ** ** PRIVATE CONTENTS ** imIffRead f read a Sun-TAAC image file ** imIffWrite f write a Sun-TAAC image file ** ** imIffHeaderInfo t IFF file header information ** imGetFDStr f Read a stream of bytes ** ** HISTORY ** $Log: /roq/libim/imiff.c $ * * 1 11/02/99 4:38p Zaphod ** Revision 1.24 1995/06/30 22:16:18 bduggan ** changed index to strchr ** ** Revision 1.23 1995/06/29 00:28:04 bduggan ** updated copyright year ** ** Revision 1.22 1995/06/15 20:30:31 bduggan ** changed "dont" to "don't". Added cast for strncmp. Removed prototype for strtok. ** ** Revision 1.21 1995/04/03 21:27:18 bduggan ** took out #ifdef NEWMAGIC ** ** Revision 1.20 1995/02/16 21:40:27 bduggan ** Made write function static ** ** Revision 1.19 1995/01/16 22:09:45 bduggan ** Added prototype for index() ** ** Revision 1.18 1995/01/10 23:31:31 bduggan ** uncapitlized i's in local functions ** put in IMMULTI, IMPIPE instead of TRUE/FALSE ** ** Revision 1.18 1995/01/10 23:31:31 bduggan ** uncapitlized i's in local functions ** put in IMMULTI, IMPIPE instead of TRUE/FALSE ** ** Revision 1.17 94/10/03 11:30:16 nadeau ** Updated to ANSI C and C++ compatibility. ** Removed all use of register keyword. ** Minimized use of custom SDSC types (e.g., uchar vs. unsigned char) ** Changed all float arguments to double. ** Added forward declarations. ** Added misc. casts to passify SGI and DEC compilers. ** Changed all macros and defined constants to have names ** starting with IM. ** Rearranged magic number structures for format handlers. ** Made format handler routines static (i.e., local to file). ** Updated comments, adding format descriptions and references. ** Updated indenting on some code. ** Updated copyright message. ** ** Revision 1.16 92/12/03 01:49:45 nadeau ** Corrected info messages. ** ** Revision 1.15 92/11/23 18:42:36 nadeau ** Removed use of IMINFOMSG. ** ** Revision 1.14 92/11/04 11:58:35 groening ** put ImFIleFormat info and magic number info ** from imfmt.c into this file. ** ** Revision 1.13 92/10/19 14:14:10 groening ** added ImInfo statements ** ** Revision 1.12 92/09/02 15:58:04 vle ** Updated copyright notice. ** ** Revision 1.11 92/09/02 15:48:31 todd ** modify to handle sun VX/MVX vff files. minor changes. ** ** Revision 1.10 92/04/09 09:31:00 groening ** To make the compiler happy added extern statements. ** ** Revision 1.9 91/10/04 10:50:21 nadeau ** Fixed shift problem for VAX. ** ** Revision 1.8 91/10/03 09:06:07 nadeau ** Fixed #includes. ** ** Revision 1.7 91/02/12 11:33:09 nadeau ** Removed the tag table checking now handled by ** ImFileRead and ImFileWrite. ** ** Revision 1.6 91/01/29 11:09:03 todd ** minor changes ** ** Revision 1.5 90/09/18 08:18:08 todd ** Added 8 bit image with colormap functionality. ** cleaned up header reading code. ** ** Revision 1.4 90/07/02 13:20:03 nadeau ** Updated to the new error handling mechanism. ** ** Revision 1.3 90/06/25 14:46:36 nadeau ** Changed ImTag* to Tag* (new names). ** ** Revision 1.2 90/06/25 13:22:24 todd ** Fixed a few little bugs. Version 2.4 of voxvu write ^L out to the ** image file as the ascii string "^L" where version 2.3 writes it out ** as the printf string "\f". I think this is a bug in 2.4. I haven't ** done anything about it yet. ** ** Revision 1.1 90/04/05 17:05:53 todd ** Initial revision ** **/ #include "iminternal.h" /** ** ** FORMAT ** IFF - Sun TAAC Image File Format ** ** AKA ** vff, suniff, taac ** ** FORMAT REFERENCES ** Sun-Taac User Manual, Volume Rendering Package, Sun Microsystems ** ** CODE CREDITS ** Custom development, Todd Elvins, San Diego Supercomputer Center, 1990. ** ** DESCRIPTION ** A typical IFF ascii header looks like this: ** ** ncaa ** rank=2; ** size=512 512; ** bands=3; ** bits=8 8 8; ** format=base; ** ^L ** (followed by lots of raw pixel data) ** ** The header can also contain a colormap such as this one: ** bands=1; ** bits=8; ** colormapsize=256; ** colormap= ... ** ** ** Storage formats "Block Pseudo" and "Two Bit Movie Dump" are specific ** to the Sun-TAAC system, and may well become obsolete within 6 months. ** For these reasons they are not supported at this time. ** ** ** **/ #ifdef __STDC__ static int imIffRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ); static int imIffWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ); #else static int imIffRead( ), imIffWrite( ); #endif static char *imIffNames[ ] = { "iff", "vff", "suniff", "taac", NULL }; static unsigned char imIffMagicNumber[ ] = { 'n', 'c', 'a', 'a' }; static ImFileMagic imFileIffMagic []= { { 0, 4, imIffMagicNumber}, { 0, 0, NULL }, }; static ImFileFormatReadMap imIffReadMap[ ] = { /* in out */ /* type,ch,dep, attr. VFB type attr. */ { IN,1,8, 0, IMVFBINDEX8, 0 }, { IN,1,8, C, IMVFBINDEX8, C }, { RGB,3,8, 0, IMVFBRGB, 0 }, { RGB,3,8, A, IMVFBRGB, A }, { -1, 0, -1, 0 }, }; static ImFileFormatWriteMap imIffWriteMap[ ] = { /* in out */ /* VFB type, attr., type,ch,dep, attr., func */ { IMVFBINDEX8, 0, IN,1,8, 0, imIffWrite }, { IMVFBINDEX8, C, IN,1,8, C, imIffWrite }, { IMVFBRGB, 0, RGB,3,8, 0, imIffWrite }, { IMVFBRGB, A, RGB,3,8, A, imIffWrite }, { -1, 0, -1, 0, NULL }, }; ImFileFormat ImFileIffFormat = { imIffNames, "Sun TAAC Image File Format", "Sun Microsystems, Inc.", "8-bit, 24-bit RGB, and 32-bit RGB+alpha image.", "8-bit, 24-bit RGB, and 32-bit RGB+alpha image.", imFileIffMagic, IMNOMULTI, IMNOPIPE, IMNOMULTI, IMNOPIPE, imIffRead, imIffReadMap, imIffWriteMap }; /* * TYPEDEF & STRUCTURE * IMIFFMAGIC The magic number at the beginning of an IFF file. * IMIFFMAGICCNT The number of bytes of magic number in an IFF file. * IMIFF24BITHEADSTRINGS Required number of keywords * IMIFFHEADSTRINGS Required plus optional keywords * IMIFFSTRLENGTH The number of bytes in a long string. * IMIFFLONGBUFF In case we have to read in an ascii colormap * IMRANK The index of the rank entry in the imIffHeader array. * IMSIZE The index of the size entry in the imIffHeader array. * IMBANDS The index of the bands entry in the imIffHeader array. * IMBITS The index of the bits entry in the imIffHeader array. * IMFORMAT The index of the format entry in the imIffHeader array. * IMCOLORMAPSIZE The index of the colormapsize entry in imIffHeader array * IMCOLORMAP The index of the colormap entry in the imIffHeader array * * DESCRIPTION * These are keywords to be expected in an IFF file image header. */ #ifdef __STDC__ static int imGetFDStr( int ioType, int fd, FILE *fp, char *s ); #else static int imGetFDStr( ); #endif #define IMIFFMAGIC "ncaa" #define IMIFFMAGICCNT 4 #define IMIFFSTARTPIXELS 1 #define IMIFF24BITHEADSTRINGS 5 #define IMIFFHEADSTRINGS 7 #define IMIFFSTRLENGTH 256 #define IMIFFLONGBUF 8192 #define IMRANK 0 #define IMSIZE 1 #define IMBANDS 2 #define IMBITS 3 #define IMFORMAT 4 #define IMCOLORMAPSIZE 5 #define IMCOLORMAP 6 /* * TYPEDEF & STRUCTURE * imIffHeader - IFF file header information * * DESCRIPTION * A IFF file's header contains the image's dimensionality, * width, height, depth, bits/pixel, and storage. */ typedef struct imIffHeaderInfo { char *name; int set; } imIffHeaderInfo ; static imIffHeaderInfo imIffHeader[] = { "rank", FALSE, "size", FALSE, "bands", FALSE, "bits", FALSE, "format", FALSE, "colormapsize", FALSE, "colormap", FALSE } ; /* * FUNCTION * imGetFDStr - Read a stream of bytes * * DESCRIPTION * Read from the file descriptor fd until EOL. Put the string * into s. Return -1 on failure. */ static int #ifdef __STDC__ imGetFDStr( int ioType, int fd, FILE *fp, char *s ) #else imGetFDStr( ioType, fd, fp, s ) int ioType; int fd; FILE *fp; char *s; #endif { char *buf; /* The buffer to fill up */ int cnt; /* Count the number of byte read */ buf = s; cnt = 0; do { if ( ImBinRead( ioType, fd, fp, buf, CHAR, 1, 1 ) == -1 ) { ImReturnBinError( ); } if (++cnt >= IMIFFLONGBUF ) { ImErrNo = IMESYNTAX; ImErrorFatal( ImQError( ), -1, ImErrNo ); } if (*buf == 0x0c ) /* ^L */ { /* Skip the following carriage return */ if ( ImBinRead( ioType, fd, fp, buf, CHAR, 1, 1 )== -1) { ImReturnBinError( ); } return( IMIFFSTARTPIXELS ); } } while ( *buf++ != '\n' ); *--buf = '\0'; return( 0 ); } /* * FUNCTION * imIffRead - read a Sun-TAAC image file * * DESCRIPTION * The file header is read and the size of the image determined. * Space is allocated for the VFB. The image data is stored in * either RGB or RGBA. The RGB[A] data is read into the VFB one * scanline at a time and the completed VFB is added to the tag list. */ static int /* Returns # tags read in */ #ifdef __STDC__ imIffRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ) #else imIffRead( ioType, fd, fp, flagsTable, tagTable ) int ioType; /* I/O flags */ int fd; /* Input file descriptor */ FILE *fp; /* Input file pointer */ TagTable *flagsTable; /* Flags */ TagTable *tagTable; /* Tag list to add to */ #endif { ImVfb *vfb; /* Read in image */ ImVfbPtr pptr; /* Pixel pointer */ ImClt *clt=NULL; /* Read in image */ ImCltPtr cptr; /* Pixel pointer */ unsigned char *runBuffer; /* Run buffer */ unsigned char *rbp; /* Run buffer pointer */ char *eSign; /* Pointer into an input string*/ char *nextstr; /* Pointer into an input string*/ unsigned char magic[IMIFFSTRLENGTH]; /* Store the magic number*/ char buf[IMIFFLONGBUF]; /* Keyword buffer */ char key[IMIFFSTRLENGTH]; /* Keyword buffer */ char format[IMIFFSTRLENGTH]; /* Storage == "Base" */ char msg[IMIFFSTRLENGTH]; /* Tmp message holder */ int rank; /* Dimensionality */ int sizex, sizey; /* Image width and height */ int bands; /* Either 3 or 4 RGB or RGBA */ int bitsr,bitsg,bitsb,bitsa; /* Image depth */ int status; /* Returned function status */ int cltsize; /* How many clt entries */ unsigned int rgbFlag; /* Is there an alpha channel */ unsigned int rgbvals; /* An rgb clt entry */ int i,j,cnt=0; /* Loop counters */ char message[100]; /* ImInfo message */ /* * IFF files are usually generated on Sun-TAACs, which have an MBF * byte order. There is no floating point in the file so we * won't bother setting the float format for BIN. */ BinByteOrder( BINMBF ); /* * Read in the magic number and check it. */ if ( ImBinRead( ioType, fd, fp, magic, UCHAR, 1, IMIFFMAGICCNT+1)== -1 ) ImReturnBinError( ); if ( strncmp( IMIFFMAGIC, (char*)magic, IMIFFMAGICCNT ) != 0) { ImErrNo = IMEMAGIC; ImErrorFatal( ImQError( ), -1, ImErrNo ); } /* * Read in the file header. */ while((status = imGetFDStr( ioType, fd, fp, buf )) != IMIFFSTARTPIXELS ) { if ( status == -1 ) return( -1 ); /* ImErrNo already set */ if ( *buf == '\n' || *buf == '\0' ) continue; /* * Get the keyword out of the string into key var */ if ( (eSign = (char *)strchr( buf, '=' )) == NULL ) { ImErrNo = IMESYNTAX; ImErrorFatal( ImQError( ), -1, ImErrNo ); } *eSign++ = '\0'; /* Skip the equal sign */ sscanf( buf, "%s", key ); /* * Look in the table of known keywords for a match */ for( j=0; j>16 & 0xff ); ImCltSGreen( cptr, rgbvals>> 8 & 0xff ); ImCltSRed( cptr, rgbvals & 0xff ); ImCltSInc( clt, cptr ); for( i=1; i>16 & 0xff ); ImCltSGreen( cptr, rgbvals>> 8 & 0xff ); ImCltSRed( cptr, rgbvals & 0xff ); ImCltSInc( clt, cptr ); } break; default: sprintf( msg, "Unknown keyword '%s' in file header\n", key ); ImErrorWarning( msg, -1, IMESYNTAX ); } /* end switch */ } /* end foreach keyword loop */ /* * Do sanity checking. Some of the keywords are mandatory. */ for( i=0; imap_outAttributes & IMALPHAYES ) bands++; } /* * IFF files are usually generated on Sun-TAACs, which have an MBF * byte order. There is no floating point in the file so we * won't bother setting the float format for BIN. */ BinByteOrder( BINMBF ); /* * Set up the header and write it out. */ sizex = ImVfbQWidth( vfb ); sizey = ImVfbQHeight( vfb ); /* * Dump out the ascii header */ sprintf( buf, "ncaa\n\0" ); /* Magic */ ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); sprintf( buf, "rank=%d;\n\0", 2 ); /* Two dimensional */ ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); sprintf( buf, "bands=%d;\n\0", bands ); /* Depth */ ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); sprintf( buf, "size=%d %d;\n\0", sizex, sizey );/* Width height */ ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); sprintf (message, "%d x %d",sizex,sizey); ImInfo ("Resolution",message); sprintf( buf, "format=%s;\n\0", "base" ); /* Storage format */ ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); if ( bands == 1 ) { sprintf( buf, "bits=%d;\n\0", bits ); ImInfo ("Type","8-bit Color Indexed"); } else if ( bands == 3 ) { sprintf( buf, "bits=%d %d %d;\n\0", bits, bits, bits ); ImInfo ("Type","24-bit RGB"); } else if ( bands == 4 ) { sprintf( buf, "bits=%d %d %d %d;\n\0", bits, bits, bits, bits ); ImInfo ("Type","32-bit RGB and Alpha"); } ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); if ( pMap->map_outAttributes & IMCLTYES ) { clt = ImVfbQClt( vfb ); cltsize = ImCltQNColors( clt ); pclt = ImCltQFirst( clt ); sprintf (message, "%d Entries",cltsize); ImInfo ("Color Table",message); sprintf( buf, "colormapsize=%d;\n\0", cltsize); ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); sprintf( buf, "colormap=\0"); ImBinWrite( ioType, fd, fp, buf, UCHAR, 1, strlen(buf) ); for( i=0; i