/** ** $Header: /roq/libim/imrla.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/imrla.c 1 11/02/99 4:38p Zaphod $" /** ** FILE ** imrla.c - Wavefront RLA/RLB file I/O ** ** PROJECT ** libim - SDSC image manipulation library ** ** DESCRIPTION ** imrla.c contains routines to read and write Wavefront RLA/RLB files for ** the image manipulation library. ** ** NOTE: rla files have their origin in the lower left corner. VFBs ** have their origin in the upper left corner so we have to read and ** write our VFB scanlines in reverse order. ** ** PUBLIC CONTENTS ** d =defined constant ** f =function ** m =defined macro ** t =typedef/struct/union ** v =variable ** ? =other ** ** PRIVATE CONTENTS ** ** imRlaRead f read a Wavefront RLA/RLB file ** imRlaWrite f write a Wavefront RLA/RLB file ** ** NULL d an empty pointer ** ** imRlaHeaderInfo t RLA header ** imRlaHeaderFields t RLA header description for Bin pkg ** imRlaPrHeader f Debug routine for printing header ** imRlaPrWindow f Debug routine for printing header ** imRlaDecode f decode one scanline of pixel values ** imRlaEncode f encode one scanline of pixel values ** ** HISTORY ** $Log: /roq/libim/imrla.c $ * * 1 11/02/99 4:38p Zaphod ** Revision 1.23 1995/06/30 22:09:41 bduggan ** fixed very weird bug with c++ on decalpha. ** (prob'ly a compiler bug.) ** ** Revision 1.22 1995/06/29 00:28:04 bduggan ** updated copyright year ** ** Revision 1.21 1995/06/15 21:12:27 bduggan ** changed bzero to memset. added include ** ** Revision 1.20 1995/04/03 21:36:19 bduggan ** took out #ifdef NEWMAGIC ** ** Revision 1.19 1995/01/10 23:42:38 bduggan ** put in IMMULTI, IMPIPE instead of TRUE/FALSE ** made read/write routines static ** ** Revision 1.18 94/10/03 11:30:53 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.17 93/09/22 11:41:33 nadeau ** Corrected resolution calculation for info message. ** ** Revision 1.16 92/12/03 01:52:08 nadeau ** Corrected info messages. ** ** Revision 1.15 92/11/04 12:07:00 groening ** put ImFIleFormat info and magic number info ** from imfmt.c into this file. ** ** Revision 1.14 92/10/19 14:11:06 groening ** added ImInfo statements ** ** Revision 1.13 92/08/31 17:34:37 vle ** Updated copyright notice. ** ** Revision 1.12 91/10/04 08:40:11 nadeau ** Fixed bad strcpy. ** ** Revision 1.11 91/10/03 09:18:08 nadeau ** Removed bogus PVFILE header field and merged with ** GAMMA field. Rearranged RGB read and write loops. ** Expanded window structure into header structure to ** avoid struct padding quirks of some C compilers. ** ** Revision 1.10 91/03/18 15:45:37 todd ** added a call to bzero to fix a bug on the cray ** ** Revision 1.9 91/02/12 11:37:21 nadeau ** Removed the tag table checking and VFB conversion now ** handled by ImFileRead and ImFileWrite. Removed pipe ** handling. ** ** Revision 1.8 91/01/29 11:09:44 todd ** make alpha channel optional ** ** Revision 1.7 90/11/30 14:39:48 mercurio ** Unchanged wrt 1.6 ** ** Revision 1.6 90/09/07 16:02:38 mercurio ** Read function now clears VFB to all zeros before filling (important-- ** since only the active area is filled explicitly). ** ** Revision 1.5 90/07/25 14:23:24 mercurio ** Fixed read routine to read entire window, not just active window ** ** Revision 1.4 90/07/02 13:21:56 nadeau ** Updated to the new error handling mechanism. ** ** Revision 1.3 90/06/25 14:47:39 nadeau ** Changed ImTag* to Tag* (new names). ** ** Revision 1.2 90/06/25 13:19:49 todd ** Lots of changes and functionality added. Works with pipes. ** Both RLA and RLB formats accepted. Fixed bugs. Tested. ** ** Revision 1.1 90/04/11 08:37:46 todd ** Initial revision ** ** **/ /** ** FORMAT ** RLA - Wavefront run length encoded format ** ** AKA ** .rlb, .rle ** ** FORMAT REFERENCES ** Run Length Encoded File Format, ".rla", Techinal Memo 860605, ** Wavefront Technologies ** ** CODE CREDITS ** Custom development, Dave Nadeau, San Diego Supercomputer Center, 1990. ** Custom development, Todd Elvins, San Diego Supercomputer Center, 1990. ** ** DESCRIPTION ** ** All data in these files are stored Most Significant Byte first. ** The files are sequential scan-line write, and random scan-line read. A ** scanline offset table is used to locate the beginning of each encoded ** scanline within the file. ** ** The file is organized into three sections: ** - header 740 bytes ** - offset table 4*(y resolution;( # of scanlines) bytes ** - encoded channel data variable length ** ** ====== ** Header ** ====== ** ** short window_left; Boundaries of complete image ** short window_right; ** short window_bottom; ** short window_top; ** short active_window_left; Boundaries of non-zero image ** short active_window_right; ** short active_window_bottom; ** short active_window_top; ** ** The active_window values specify the dimensions for what is encoded. ** The window values specify the dimensions for the complete image. ** ** short frame; Frame number ** ** The frame number in a sequence of frames. ** ** short storage_type; Byte or word data ** ** Specifies whether it is byte or word data. ** ** short num_chan; Number of image channels ** ** Typically 3 for R,G,B. ** ** short num_matte; Number of matte channels ** ** 0 = no alpha channel. 1 = alpha channel. ** Could be more if the transparency information includes spectral ** information. ** ** short num_aux; Number of aux channels ** short aux_mask; Aux channel type mask ** ** num_aux is the number of auxillary channels. Auxillary channel ** information could include distance from the eye, direction of normal, ** etc. There are typically 0 auxillary channels. ** aux_mask is a bitmask that describes what is in the auxiallry channels. ** The interpretation of this bitmask is governed by the fmt__aux_chan ** table in the system configuration file. ** ** char gamma[IMRLANGAMMA]; Image storage gamma ** ** Floating point number: gamma that was applied to the file for storage. ** ** char red_pri[IMRLANPRI]; Image red primary chromaticity ** char green_pri[IMRLANPRI]; Image grn primary chromaticity ** char blue_pri[IMRLANPRI]; Image blu primary chromaticity ** char white_pt[IMRLANPRI]; White point ** ** Chromaticities of the red, green, and blue primaries, and the white ** point that were used to store the image, if it was an rgb image. ** Each field contains the x,y chromaticity as two floating point ** numbers seperated by a space. ** ** int job_num; Job Number ** char name[IMRLANNAME]; Original file name ** char desc[IMRLANNAME]; File description number ** char program[IMRLANPROG]; Creating program name ** char machine[IMRLANSTR]; Creating machine name ** char user[IMRLANSTR]; Creating user ** char date[IMRLANDATE]; Creation date ** ** Various informative pieces of data. ** ** char aspect[IMRLANASPECT]; Image aspect type ** char aspect_ratio[IMRLANAR]; Image aspect ratio ** ** Aspect ratio for the image. ** ** char chan[IMRLANSTR]; Image color space type ** ** Must be 'rgb' ** ** short field; Rendered on fields flag ** short filter_type; Post filtered interleaved flag ** int magic_number; unused ** int lut_size; unused ** int user_space_size; unused ** int wf_space_size; unused ** short lut_type; unused ** short mix_type; unused ** short encode_type; unused ** short padding; unused ** char space[IMRLANSPACE]; Unused expansion space ** ** Unused fields. ** ** ============ ** Offset Table ** ============ ** ** The length of each encoded scanline varies, depending on how well the ** encoding algorithm compresses the scanline. The offset table contains ** the starting positions of each scanline. ** ** ==================== ** Encoded Channel Data ** ==================== ** ** All of the data for one particular scanline appears sequentially in ** a file. If an image has an r,g,b, and alpha channel, then there will ** be a record for the red channel, followed by a record for the green ** channel, followed by a record for the blue channel, followed by a ** record for the alpha channel. ** The offset (from the offset table) points to the beginning of the record ** for the red channel. A record is of the form: ** ** - length 2 bytes ** - encoded string data length bytes ** ** The encoding scheme is fairly simple. It consists of a series of 'run's. ** There are two types of runs: verbatim and compressed. A run looks ** like this: ** ** - count 2 byte signed integer ** - data MAX(1,-count) bytes of data ** ** If the count is positive then this is a compressed run. In this case, ** the data is simply a value, which is to be repeated count+1 times. ** ** If the count is negative, then the next -count bytes of data are to be ** copied verbatim into the image. ** ** Data is not compressed if the repeat count is two or less. **/ #include //#include #include "iminternal.h" /* * RLA/RLB - Wavefront image file * For information on these structures, how to use them, etc. please * see imfmt.c. */ #ifdef __STDC__ static int imRlaRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ); static int imRlaWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ); #else static int imRlaRead( ), imRlaWrite( ); #endif static char *imRlaNames[ ] = { "rla", "rlb", NULL }; static ImFileFormatReadMap imRlaReadMap[ ] = { /* in out */ /* type,ch,dep, attr. VFB type attr. */ { RGB,3,8, RLE, IMVFBRGB, 0 }, { RGB,3,8, RLE|A, IMVFBRGB, A }, { -1, 0, -1, 0 }, }; static ImFileFormatWriteMap imRlaWriteMap[ ] = { /* in out */ /* VFB type, attr., type,ch,dep, attr., func */ { IMVFBRGB, 0, RGB,3,8, RLE|A, imRlaWrite }, { IMVFBRGB, A, RGB,3,8, RLE|A, imRlaWrite }, { -1, 0, -1, 0, NULL }, }; static ImFileMagic imFileRlaMagic []= { { 0, 0, NULL }, }; ImFileFormat ImFileRlaFormat = { imRlaNames, "Wavefront raster image file", "Wavefront", "24-bit RGB and 32-bit RGB+alpha RLE-compressed image files in both\n\ RLB and the older RLA format.", "24-bit RGB and 32-bit RGB+alpha RLE-compressed image files in RLB\n\ format.", imFileRlaMagic, IMNOMULTI, IMNOPIPE, IMNOMULTI, IMNOPIPE, imRlaRead, imRlaReadMap, imRlaWriteMap }; /* * TYPEDEF & STRUCTURE * imRlaHeaderInfo - RLA file header information * imRlaHeaderFields - Description for Binio package * * DESCRIPTION * A RLA file's header contains the image's width, height, and depth, * and many other fields. */ #define IMRLANGAMMA (16) #define IMRLANPRI (24) #define IMRLANNAME (128) #define IMRLANPROG (64) #define IMRLANSTR (32) #define IMRLANDATE (20) #define IMRLANASPECT (24) #define IMRLANAR (8) #define IMRLANSPACE (100) #define IMRLAHEADERSIZE (740) typedef struct imRlaHeaderInfo { short window_left; /* Boundaries of complete image */ short window_right; short window_bottom; short window_top; short active_window_left; /* Boundaries of non-zero image */ short active_window_right; short active_window_bottom; short active_window_top; short frame; /* Frame number */ short storage_type; /* Byte or word data */ short num_chan; /* Number of image channels */ short num_matte; /* Number of matte channels */ short num_aux; /* Number of aux channels */ short aux_mask; /* Aux channel type mask */ char gamma[IMRLANGAMMA]; /* Image storage gamma */ char red_pri[IMRLANPRI]; /* Image red primary chromaticity */ char green_pri[IMRLANPRI]; /* Image grn primary chromaticity */ char blue_pri[IMRLANPRI]; /* Image blu primary chromaticity */ char white_pt[IMRLANPRI]; /* White point */ int job_num; /* Job Number */ char name[IMRLANNAME]; /* Original file name */ char desc[IMRLANNAME]; /* File description number */ char program[IMRLANPROG]; /* Creating program name */ char machine[IMRLANSTR]; /* Creating machine name */ char user[IMRLANSTR]; /* Creating user */ char date[IMRLANDATE]; /* Creation date */ char aspect[IMRLANASPECT]; /* Image aspect type */ char aspect_ratio[IMRLANAR]; /* Image aspect ratio */ char chan[IMRLANSTR]; /* Image color space type */ short field; /* Rendered on fields flag */ short filter_type; /* Post filtered interleaved flag*/ int magic_number; /* unused */ int lut_size; /* unused */ int user_space_size; /* unused */ int wf_space_size; /* unused */ short lut_type; /* unused */ short mix_type; /* unused */ short encode_type; /* unused */ short padding; /* unused */ char space[IMRLANSPACE]; /* Unused expansion space */ } imRlaHeaderInfo; BinField imRlaHeaderFields[ ] = { { SHORT, 2, 1 }, /* Window boundaries */ { SHORT, 2, 1 }, { SHORT, 2, 1 }, { SHORT, 2, 1 }, { SHORT, 2, 1 }, /* Active window boundaries */ { SHORT, 2, 1 }, { SHORT, 2, 1 }, { SHORT, 2, 1 }, { SHORT, 2, 1 }, /* Frame */ { SHORT, 2, 1 }, /* Storage type */ { SHORT, 2, 1 }, /* Number of image channels */ { SHORT, 2, 1 }, /* Number of matte channels */ { SHORT, 2, 1 }, /* Number of aux channels */ { SHORT, 2, 1 }, /* Aux channel type mask */ { CHAR, 1, IMRLANGAMMA }, /* Image storage gamma */ { CHAR, 1, IMRLANPRI }, /* Image red primary chromaticity */ { CHAR, 1, IMRLANPRI }, /* Image grn primary chromaticity */ { CHAR, 1, IMRLANPRI }, /* Image blu primary chromaticity */ { CHAR, 1, IMRLANPRI }, /* Image whi primary chromaticity */ { INT, 4, 1 }, /* Job number */ { CHAR, 1, IMRLANNAME }, /* Original file name */ { CHAR, 1, IMRLANNAME }, /* File description */ { CHAR, 1, IMRLANPROG }, /* Creating program name */ { CHAR, 1, IMRLANSTR }, /* Creating machine name */ { CHAR, 1, IMRLANSTR }, /* Creating user name */ { CHAR, 1, IMRLANDATE }, /* Creation date */ { CHAR, 1, IMRLANASPECT }, /* Image aspect type */ { CHAR, 1, IMRLANAR }, /* Image aspect ratio */ { CHAR, 1, IMRLANSTR }, /* Image color space type */ { SHORT, 2, 1 }, /* Rendered on fields flag */ { SHORT, 2, 1 }, /* Post filtered interleaved flag*/ { INT, 4, 1 }, /* unused */ { INT, 4, 1 }, /* unused */ { INT, 4, 1 }, /* unused */ { INT, 4, 1 }, /* unused */ { SHORT, 2, 1 }, /* unused */ { SHORT, 2, 1 }, /* unused */ { SHORT, 2, 1 }, /* unused */ { SHORT, 2, 1 }, /* unused */ { CHAR, 1, IMRLANSPACE }, /* Unused expansion space */ { 0, 0, 0 } }; /* * MACRO * imRlaFrBuf - Free six chunks of memory * * DESCRIPTION * Call free six times to free the six chunks of memory pointed to by * a-f. */ #define imRlaFrBuf(a,b,c,d,e,f) free((a));free((b));free((c));free((d));free((e));free((f)) /* * FUNCTION * imPrRlaHeader - print out the header of a rla file * * DESCRIPTION * The contents of the ImRlaHeader structure is printed on the * standard error. */ static void #ifdef __STDC__ imRlaPrHeader(imRlaHeaderInfo *p) #else imRlaPrHeader(p) imRlaHeaderInfo *p; #endif { char message[200]; /* contains information for ImInfo */ ImInfo ("Image Name", p->name); ImInfo ("Byte Order", "Most Significant Byte First"); sprintf (message, "%d x %d", ( (p->active_window_right) - (p->active_window_left) + 1), ( (p->active_window_top) - (p->active_window_bottom) + 1)); ImInfo ("Resolution", message); if (p->storage_type==0) sprintf ( message , "24 bit RGB"); else sprintf ( message , "3 word RGB"); ImInfo ("Type",message); if (p->num_matte>0) { if (p->storage_type==0) sprintf ( message , "8 bit"); else sprintf ( message , "1 word"); } else sprintf (message, "None"); ImInfo ("Alpha Channel", message); #ifdef DEBUG fprintf(stderr,"Channels: Image %d Matte %d Aux %d Aux Mask %02x\n", p->num_chan, p->num_matte, p->num_aux, p->aux_mask); fprintf(stderr,"Job Number %ld Name \"%s\"\n",p->job_num,p->name); fprintf(stderr,"Desc \"%s\"\n",p->desc); fprintf(stderr,"Program \"%s\" Machine \"%s\"\n",p->program,p->machine); fprintf(stderr,"User %s Date %s Aspect %s Aspect ratio %s\n", p->user,p->date,p->aspect,p->aspect_ratio); fprintf(stderr,"Chan %s Field %d Filter_type %d Magic %d\n", p->chan, p->field, p->filter_type, p->magic_number ); #endif sprintf (message, "%d", p->frame); ImInfo ("Frame Number", message); ImInfo ( "Gamma", p->gamma); ImInfo ( "Red Primary", p->red_pri); ImInfo ( "Green Primary", p->green_pri); ImInfo ( "Blue Primary", p->blue_pri); ImInfo ( "White Point", p->white_pt); } /* * FUNCTION * imRlaDecode - decode one channel of one scanline * * DESCRIPTION * One channel of one scanline (cIn) in Wavefront RLA format is decoded * and returned in cOut. len is the number of bytes in cIn. */ static void #ifdef __STDC__ imRlaDecode( unsigned char *cIn, unsigned char *cOut, int len ) #else imRlaDecode( cIn, cOut, len ) unsigned char *cIn; unsigned char *cOut; int len; #endif { int cnt; /* * Loop through the bytes to be decoded */ while( len > 0 ) { cnt = *cIn++; len--; if ( cnt < 128 ) { /* * Repeat pixel value cnt+1 times */ while ( cnt-- >= 0 ) *cOut++ = *cIn; cIn++; len--; } else /* * Just copy the unencoded bytes directly */ for ( cnt=256-cnt; cnt-- > 0; len-- ) *cOut++ = *cIn++; } } /* * FUNCTION * imRlaRead - read an Wavefront RLA file * * DESCRIPTION * The file header is read and the size of the image determined. * Space is allocated for the VFB and the run codes read in to * a run buffer. The run buffer is then expanded into straight * RGB values in the VFB and the completed VFB added to the tag table. */ static int /* Returns # tags read in */ #ifdef __STDC__ imRlaRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ) #else imRlaRead( 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 */ ImVfbPtr leftpptr; /* Points to start of scanlines */ imRlaHeaderInfo header; /* RLA file header */ unsigned char *redBuf; /* Run buffer */ unsigned char *grnBuf; /* Run buffer */ unsigned char *bluBuf; /* Run buffer */ unsigned char *alpBuf; /* Run buffer */ unsigned char *buf; /* Run buffer */ short len; /* Number of bytes unencoded */ int *offsetTable; /* Array of scanline offsets */ int status; /* Status returned from seek */ int x,y,dep; /* Convenient short names */ int i,j; /* Loop counters */ int width; /* true width of image */ int height; /* true height of image */ int bPad; /* bottom padding amount */ int lPad; /* left padding amount */ unsigned char* freak; /* See the paragraph below */ /* The variable 'freak' is to have a totally gratuitous * cast from an int into an unsigned char*. The purpose * of this is to stop the decalpha c++ compiler from making * some sort of weird crazy screwed up optimization that * results in an endless loop. * * I don't understand why this works. But take out the * cast, and this routine won't work on decalpha's with c++. * * You don't believe me? Try it! * * I haven't had enough free time to investigate this compiler * bug, or pinpoint it very well. */ /* * RLA files are usually generated on Irises, 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 header. */ if (ImBinReadStruct(ioType, fd, fp, &header, imRlaHeaderFields ) == -1) { ImReturnBinError( ); } imRlaPrHeader( &header ); width = 1 + header.window_right - header.window_left; height = 1 + header.window_top - header.window_bottom; x = 1 + header.active_window_right - header.active_window_left; y = 1 + header.active_window_top - header.active_window_bottom; bPad = (int) (header.active_window_bottom - header.window_bottom); lPad = (int) (header.active_window_left - header.window_left); /* * Here's the moronic hack of all hacks to defeat * the evil decalpha c++ compiler: */ freak = (unsigned char*)&lPad; dep = header.num_chan + header.num_matte; /* * Check the important header parameters for legal bounds. * header.chan must be 'rgb' * x and y must have positive active window size * image depth must be 3 (RGB) or 4 (RGBA) * header.num_aux must be 0 * * We'd like to check these as well, however while RLB files have * them, RLA files don't, so we just skip checking their values. * header.field must be 0 * header.magic_number must be 0 * header.filter_type must be 0 */ if ((strcmp( header.chan, "rgb" ) != 0) || x < 1 || y < 1 || (dep != 4 && dep != 3) || header.num_aux != 0 ) { ImErrNo = IMESYNTAX; ImErrorFatal( ImQError( ), -1, ImErrNo ); } /* * Allocate space for the offset table and read it in */ ImMalloc( offsetTable, int *, sizeof(int) * y ); if ( ImBinRead( ioType, fd, fp, offsetTable, INT, 4, y ) == -1 ) { free( (char *)offsetTable ); ImReturnBinError( ); } /* * Allocate a VFB of the required size and clear it. */ if ( header.num_matte == 1 ) vfb = ImVfbAlloc( width, height, IMVFBRGB | IMVFBALPHA ); else vfb = ImVfbAlloc( width, height, IMVFBRGB ); if ( vfb == IMVFBNULL ) { free( (char *)offsetTable ); ImErrorFatal( ImQError( ), -1, ImErrNo ); } ImVfbClear( ImVfbQFields( vfb ), 0, vfb ); /* * Allocate run buffers large enough for one scanline per channel. */ ImCalloc( redBuf, unsigned char *, x, 1 ); ImCalloc( grnBuf, unsigned char *, x, 1 ); ImCalloc( bluBuf, unsigned char *, x, 1 ); ImCalloc( alpBuf, unsigned char *, x, 1 ); ImCalloc( buf, unsigned char *, x*2, 1 ); /* * Loop through the scan lines. Read in a scanline and decode it. * Once all of the channels are decoded, copy them into the vfb, * going from bottom to top. */ pptr = leftpptr = ImVfbQPtr( vfb, 0, height-bPad-1 ); for( i=0; i 0 ) { if (( width > 1 ) && ( cIn[0] == cIn[1] )) { /* Encode case */ for( cnt=2; cnt < width; cnt++ ) { if ( cIn[cnt] != cIn[cnt-1] ) break; if ( cnt >= 127 ) break; } /* Write out count */ *cOut++ = cnt-1; len++; /* Write out value */ *cOut++ = *cIn; len++; width -= cnt; cIn += cnt; } else /* Don't encode */ { for( cnt=1; cnt < width; cnt++ ) { if ((width-cnt > 1) && (cIn[cnt]==cIn[cnt+1])) break; if ( cnt >= 127 ) break; } /* Write out count */ *cOut++ = 256 - cnt; len++; /* Copy string of pixels */ for ( ; cnt-- > 0; len++, width-- ) *cOut++ = *cIn++; } } return( len ); } /* * FUNCTION * imRlaWrite - write an Wavefront RLA file * * DESCRIPTION * The VFB is queried, and the RLA file header set up and written out. * The VFB data is then read out and converted to run-codes, and those * codes written out. */ static int /* Returns # of tags used */ #ifdef __STDC__ imRlaWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable ) #else imRlaWrite( pMap, ioType, fd, fp, flagsTable, tagTable ) ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */ int ioType; /* I/O flags */ int fd; /* Input file descriptor */ FILE *fp; /* Input file pointer */ TagTable *flagsTable; /* Flags */ TagTable *tagTable; /* Tag list to read from */ #endif { int x,y,dep; /* Convenient short names */ ImVfb *vfb; /* Read in image */ imRlaHeaderInfo header; /* RLA file header */ time_t seconds; /* Return value from time() */ ImVfbPtr pptr; /* Pixel pointer */ ImVfbPtr leftpptr; /* Points to start of scanlines */ unsigned char *redBuf; /* Run buffer */ unsigned char *grnBuf; /* Run buffer */ unsigned char *bluBuf; /* Run buffer */ unsigned char *alpBuf; /* Run buffer */ unsigned char *buf; /* Run buffer */ int *offsetTable; /* Array of scanline offsets */ int writeCount; /* Keep count of file offset */ short len; /* Number of bytes unencoded */ int i,j; /* Loop counters */ char *name; /* Login name */ char tmp[100]; /* Temp buffer */ struct passwd *pass; /* Password file entry */ /* * RLA files are usually generated on Irises, 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. */ TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb ); x = ImVfbQWidth( vfb ); y = ImVfbQHeight( vfb ); header.window_right = x-1; /* Right side */ header.window_top = y-1; /* Top side */ header.window_left = 0; /* Left side */ header.window_bottom = 0; /* Bottom side */ header.active_window_right = x-1; /* Right side */ header.active_window_top = y-1; /* Top side */ header.active_window_left = 0; /* Left side */ header.active_window_bottom= 0; /* Bottom side */ header.frame = 1; /* First frame (anything) */ header.storage_type = 0; /* Image data (must be 0) */ header.num_chan = 3; /* RGB (must be 3) */ header.num_matte = 1; /* Alpha included (0 or 1) */ header.num_aux = 0; /* no aux channels (must be 0) */ header.aux_mask = 0; /* no aux channels (must be 0) */ header.job_num = 0; /* job 0 (anything) */ header.field = 0; /* not on fields (0 or 1) */ header.filter_type = 0; /* non-interleaved (0 or 1) */ header.magic_number = 0; /* no magic (must be 0) */ header.lut_size = 0; /* no CLT (must be 0) */ header.user_space_size = 0; /* no user space (must be 0) */ header.wf_space_size = 0; /* no wf space (must be 0) */ header.lut_type = 0; /* no CLT (must be 0) */ header.mix_type = 0; /* no mix (must be 0) */ header.encode_type = 0; /* no encoding (must be 0) */ header.padding = 0; /* no padding (must be 0) */ strcpy( header.gamma, "2.200" ); strcpy( header.red_pri, "00.6700 00.3300" ); strcpy( header.green_pri, "00.2100 00.7100" ); strcpy( header.blue_pri, "00.1400 00.0800" ); strcpy( header.white_pt, "00.3100 00.3160" ); strncpy( header.name, ImErrorFileName, IMRLANNAME ); strcpy( header.desc, "image file" ); strncpy( header.program, ImErrorProgramName, IMRLANPROG ); strcpy( header.chan, "rgb" ); /* if ( (name = getlogin( )) == NULL ) { pass = getpwuid( getuid( ) ); name = pass->pw_name; } */ name = "Creator"; strncpy( header.user, name, IMRLANSTR ); strcpy( header.aspect, "user defined"); sprintf( tmp, "%3.2f", (float)x/y ); strncpy( header.aspect_ratio, tmp, IMRLANAR ); seconds = time( (time_t *)NULL ); strncpy( header.date, ctime( &seconds ), 19 ); #ifndef WIN32 gethostname( header.machine, IMRLANSTR ); #else strcpy(header.machine, "jaws"); #endif /* * Write out the RLA image file header */ if (( writeCount = ImBinWriteStruct( ioType, fd, fp, &header, imRlaHeaderFields )) == -1 ) { ImReturnBinError( ); } if ( writeCount != IMRLAHEADERSIZE ) { ImErrNo = IMESYS; ImErrorFatal( ImQError( ), -1, ImErrNo ); } imRlaPrHeader( &header ); /* * Allocate an offset table and initialize it to zeroes. We'll * write it out as zeroes now, fill it while we encode the data, * then seek back and write the real table out when we're done. */ ImMalloc( offsetTable, int *, sizeof(int) * y ); memset( offsetTable, 0x00, sizeof(int) * y ); if ( ImBinWrite( ioType, fd, fp, offsetTable, INT, 4, y ) == -1 ) { free( (char *)offsetTable ); ImReturnBinError( ); } writeCount += 4 * y; /* * Allocate run buffers large enough for one scanline per color */ ImCalloc( redBuf, unsigned char *, x, 1 ); ImCalloc( grnBuf, unsigned char *, x, 1 ); ImCalloc( bluBuf, unsigned char *, x, 1 ); ImCalloc( alpBuf, unsigned char *, x, 1 ); ImCalloc( buf, unsigned char *, x*2, 1 ); /* * Loop through the scan lines, from the bottom up. Fill the * buffers with channel values, encode them, and then write them out. */ pptr = leftpptr = ImVfbQPtr( vfb, 0, y-1 ); for( i=0; i