about summary refs log tree commit diff
path: root/urt/rle_getskip.c
blob: 2482f2bff33b93fb11005f962e347eaa2d9ca30b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 * 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];
    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
            {
                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;
}