home *** CD-ROM | disk | FTP | other *** search
- /*
- * This software is copyrighted as noted below. It may be freely copied,
- * modified, and redistributed, provided that the copyright notice is
- * preserved on all copies.
- *
- * There is no warranty or other guarantee of fitness for this software,
- * it is provided solely "as is". Bug reports or fixes may be sent
- * to the author, who may or may not act on them as he desires.
- *
- * You may not include this software in a program or other software product
- * without supplying the source, or without informing the end-user that the
- * source is available for no extra charge.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- *
- * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
- * to have all "void" functions so declared.
- */
- /*
- * rle_getraw.c -
- *
- * Author: Spencer W. Thomas
- * Computer Science Dept.
- * University of Utah
- * Date: Mon Nov 10 1986
- * Copyright (c) 1986, University of Utah
- */
- #ifndef lint
- static char rcs_ident[] = "$Id: rle_getraw.c,v 3.0 90/08/03 15:20:41 spencer Exp $";
- #endif
-
- #include <stdio.h>
- #include <rle.h>
- #include <rle_raw.h>
- #ifdef USE_STDLIB_H
- #include <stdlib.h>
- #else
-
- #ifndef VOID_STAR
- extern char * malloc();
- #else
- extern void *malloc();
- #endif
- extern void free();
-
- #endif /* USE_STDLIB_H */
-
- /* Read a two-byte "short" that started in VAX (LITTLE_ENDIAN) order */
- #define VAXSHORT( var, fp )\
- { var = fgetc(fp)&0xFF; var |= (fgetc(fp)) << 8; }
-
- /* Instruction format -- first byte is opcode, second is datum. */
-
- #define OPCODE(inst) (inst[0] & ~LONG)
- #define LONGP(inst) (inst[0] & LONG)
- #define DATUM(inst) (inst[1] & 0xff) /* Make sure it's unsigned. */
-
- /*****************************************************************
- * TAG( rle_getraw )
- *
- * Get a raw scanline from the input file.
- * Inputs:
- * the_hdr: rle_hdr structure containing information about
- * the input file.
- * Outputs:
- * scanraw: an array of pointers to the individual color
- * scanlines. Scanraw is assumed to have
- * the_hdr->ncolors pointers to arrays of rle_op,
- * each of which with enough elements, at least
- * 1 + (the_hdr->xmax - the_hdr->xmin) / 3.
- * nraw: an array of integers giving the number of rle_ops for
- * each color channel.
- * Returns the current scanline number. Returns 32768 at EOF.
- * Assumptions:
- * rle_get_setup has already been called.
- * Algorithm:
- * Read input until a vertical skip is encountered,
- * decoding the instructions into the scanraw array.
- * Vertical skips that separate scanlines with no data do not
- * cause a return. In other words, the only reason for returning
- * with an empty scanline is end of file.
- *
- * When the scan_y reaches or exceeds the ymax, the rest of the
- * input image is skipped. This avoids problems with malformed
- * input files.
- */
- unsigned int
- rle_getraw( the_hdr, scanraw, nraw )
- rle_hdr *the_hdr;
- rle_op *scanraw[];
- int nraw[];
- {
- register int channel;
- register rle_op * rawp = NULL;
- FILE *infile = the_hdr->rle_file;
- char inst[2];
- int scan_x = the_hdr->xmin;
- register int was_data;
- short word, long_data, nc, been_some = 0;
-
- /* Add in vertical skip from last scanline */
- if ( the_hdr->priv.get.vert_skip > 0 )
- the_hdr->priv.get.scan_y += the_hdr->priv.get.vert_skip;
-
- /* Set run lengths to 0 */
- for ( channel = (the_hdr->alpha ? -1 : 0);
- channel < the_hdr->ncolors;
- channel++ )
- if ( RLE_BIT( *the_hdr, channel ) )
- nraw[channel] = 0;
- channel = 0;
-
- if ( the_hdr->priv.get.is_eof )
- return 32768; /* too big for 16 bits, signal EOF */
-
- /* Otherwise, read and interpret instructions until a skipLines
- * instruction is encountered.
- */
- for (was_data = 0;;)
- {
- inst[0] = getc( infile );
- inst[1] = getc( infile );
- if ( feof(infile) )
- {
- the_hdr->priv.get.is_eof = 1;
- break; /* <--- one of the exits */
- }
-
- switch( OPCODE(inst) )
- {
- case RSkipLinesOp:
- was_data = 1;
- if ( LONGP(inst) )
- {
- VAXSHORT( the_hdr->priv.get.vert_skip, infile );
- }
- else
- the_hdr->priv.get.vert_skip = DATUM(inst);
- break; /* need to break for() here, too */
-
- case RSetColorOp:
- was_data = 1;
- channel = DATUM(inst); /* select color channel */
- if ( channel == 255 )
- channel = -1;
- scan_x = the_hdr->xmin;
- if ( RLE_BIT( *the_hdr, channel ) )
- rawp = scanraw[channel];
- else
- rawp = NULL;
- break;
-
- case RSkipPixelsOp:
- was_data = 1;
- if ( LONGP(inst) )
- {
- VAXSHORT( long_data, infile );
- scan_x += long_data;
- }
- else
- {
- scan_x += DATUM(inst);
- }
- break;
-
- case RByteDataOp:
- was_data = 1;
- if ( LONGP(inst) )
- {
- VAXSHORT( nc, infile );
- }
- else
- nc = DATUM(inst);
- nc++;
- if ( rawp != NULL )
- {
- rawp->opcode = RByteDataOp;
- rawp->xloc = scan_x;
- rawp->length = nc;
- rawp->u.pixels = (rle_pixel *)malloc( (unsigned)nc );
- fread( (char *)rawp->u.pixels, 1, nc, infile );
- if ( nc & 1 )
- (void)getc( infile ); /* throw away odd byte */
- rawp++;
- nraw[channel]++;
- }
- else
- if ( the_hdr->priv.get.is_seek )
- fseek( infile, ((nc + 1) / 2) * 2, 1 );
- else
- {
- register int ii;
- for ( ii = ((nc + 1) / 2) * 2; ii > 0; ii-- )
- (void) getc( infile ); /* discard it */
- }
-
- scan_x += nc;
- been_some = 1;
- break;
-
- case RRunDataOp:
- was_data = 1;
- if ( LONGP(inst) )
- {
- VAXSHORT( nc, infile );
- }
- else
- nc = DATUM(inst);
-
- nc++;
- VAXSHORT( word, infile );
- if ( rawp != NULL )
- {
- rawp->opcode = RRunDataOp;
- rawp->xloc = scan_x;
- rawp->length = nc;
- rawp->u.run_val = word;
- rawp++;
- nraw[channel]++;
- }
- scan_x += nc;
- been_some = 1;
- break;
-
- case REOFOp:
- the_hdr->priv.get.is_eof = 1;
- break;
-
- default:
- fprintf( stderr, "rle_getraw: Unrecognized opcode: %d\n", OPCODE(inst) );
- exit(1);
- }
- if ( OPCODE(inst) == REOFOp )
- break; /* <--- the other loop exit */
- if ( OPCODE(inst) == RSkipLinesOp )
- {
- if ( been_some )
- break; /* <--- the other loop exit */
- else
- /* No data on that scanline, so move up to this scanline */
- the_hdr->priv.get.scan_y +=
- the_hdr->priv.get.vert_skip;
- }
- }
-
- /* If at top of image, skip any remaining. */
- if ( the_hdr->priv.get.scan_y >= the_hdr->ymax )
- {
- int y = the_hdr->priv.get.scan_y;
- while ( rle_getskip( the_hdr ) != 32768 )
- ;
- return y;
- }
-
- /* Return current Y value */
- return (was_data == 0) ? 32768 : the_hdr->priv.get.scan_y;
- }
-
- /*****************************************************************
- * TAG( rle_freeraw )
- *
- * Free all the pixel arrays in the raw scan struct.
- * Inputs:
- * the_hdr: Header struct corresponding to this RLE data.
- * scanraw: Array of pointers to array of rle_op, as above.
- * nraw: Array of lengths (as above)
- * Outputs:
- * Frees the areas pointed to by the pixels elements of any
- * RByteDataOp type rle_op structs.
- * Assumptions:
- * [None]
- * Algorithm:
- * [None]
- */
- void
- rle_freeraw( the_hdr, scanraw, nraw )
- rle_hdr * the_hdr;
- int nraw[];
- rle_op *scanraw[] ;
- {
- int c, i;
- register rle_op * raw_p;
-
- for ( c = -the_hdr->alpha; c < the_hdr->ncolors; c++ )
- if ( RLE_BIT( *the_hdr, c ) )
- for ( i = nraw[c], raw_p = scanraw[c]; i > 0; i--, raw_p++ )
- if ( raw_p->opcode == RByteDataOp )
- free( raw_p->u.pixels );
- }
-