/*
* 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.
*/
/*
* rle_getskip.c - Skip scanlines on input.
*
* Author: Spencer W. Thomas
* EECS Dept.
* University of Michigan
* Date: Wed Jun 27 1990
* Copyright (c) 1990, University of Michigan
*/
#include <stdlib.h>
#include "rle.h"
#include "rle_code.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_getskip )
*
* Skip the next scanline with data on it.
* Most useful for skipping to end-of-image.
* Inputs:
* the_hdr: Describes input image.
* Outputs:
* Returns the number of the next scanline. At EOF returns 32768.
* Assumptions:
* rle_get_setup has been called.
* Algorithm:
* Read input to the beginning of the next scanline, or to EOF or
* end of image.
*/
unsigned int
rle_getskip( the_hdr )
rle_hdr *the_hdr;
{
unsigned char inst[2];
register FILE *infile = the_hdr->rle_file;
int nc;
/* 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;
the_hdr->priv.get.vert_skip = 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 (;;)
{
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:
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:
/* No-op here. */
break;
case RSkipPixelsOp:
if ( LONGP(inst) )
{
(void)getc( infile );
(void)getc( infile );
}
break;
case RByteDataOp:
if ( LONGP(inst) )
{
VAXSHORT( nc, infile );
}
else
nc = DATUM(inst);
nc++;
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 */
}
break;
case RRunDataOp:
if ( LONGP(inst) )
{
(void)getc( infile );
(void)getc( infile );
}
(void)getc( infile );
(void)getc( infile );
break;
case REOFOp:
the_hdr->priv.get.is_eof = 1;
break;
default:
fprintf( stderr,
"%s: rle_getskip: Unrecognized opcode: %d, reading %s\n",
the_hdr->cmd, OPCODE(inst), the_hdr->file_name );
exit(1);
}
if ( OPCODE(inst) == REOFOp )
break; /* <--- the other loop exit */
if ( OPCODE(inst) == RSkipLinesOp )
break;
}
/* Return the number of the NEXT scanline. */
the_hdr->priv.get.scan_y +=
the_hdr->priv.get.vert_skip;
the_hdr->priv.get.vert_skip = 0;
if ( the_hdr->priv.get.is_eof )
return 32768; /* too big for 16 bits, signal EOF */
else
return the_hdr->priv.get.scan_y;
}