~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to plug-ins/sgi/sgilib.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * "$Id: sgilib.c,v 1.8 2003/04/07 11:59:33 neo Exp $"
 
3
 *
 
4
 *   SGI image file format library routines.
 
5
 *
 
6
 *   Copyright 1997-1998 Michael Sweet (mike@easysw.com)
 
7
 *
 
8
 *   This program is free software; you can redistribute it and/or modify it
 
9
 *   under the terms of the GNU General Public License as published by the Free
 
10
 *   Software Foundation; either version 2 of the License, or (at your option)
 
11
 *   any later version.
 
12
 *
 
13
 *   This program is distributed in the hope that it will be useful, but
 
14
 *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
15
 *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
16
 *   for more details.
 
17
 *
 
18
 *   You should have received a copy of the GNU General Public License
 
19
 *   along with this program; if not, write to the Free Software
 
20
 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
21
 *
 
22
 * Contents:
 
23
 *
 
24
 *   sgiClose()    - Close an SGI image file.
 
25
 *   sgiGetRow()   - Get a row of image data from a file.
 
26
 *   sgiOpen()     - Open an SGI image file for reading or writing.
 
27
 *   sgiOpenFile() - Open an SGI image file for reading or writing.
 
28
 *   sgiPutRow()   - Put a row of image data to a file.
 
29
 *   getlong()     - Get a 32-bit big-endian integer.
 
30
 *   getshort()    - Get a 16-bit big-endian integer.
 
31
 *   putlong()     - Put a 32-bit big-endian integer.
 
32
 *   putshort()    - Put a 16-bit big-endian integer.
 
33
 *   read_rle8()   - Read 8-bit RLE data.
 
34
 *   read_rle16()  - Read 16-bit RLE data.
 
35
 *   write_rle8()  - Write 8-bit RLE data.
 
36
 *   write_rle16() - Write 16-bit RLE data.
 
37
 *
 
38
 * Revision History:
 
39
 *
 
40
 *   $Log: sgilib.c,v $
 
41
 *   Revision 1.8  2003/04/07 11:59:33  neo
 
42
 *   2003-04-07  Sven Neumann  <sven@gimp.org>
 
43
 *
 
44
 *      * plug-ins/sgi/sgi.h
 
45
 *      * plug-ins/sgi/sgilib.c: applied a patch from marek@aki.cz that
 
46
 *      adds support for reading SGI files in little-endian format. Fixes
 
47
 *      bug #106610.
 
48
 *
 
49
 *   Revision 1.7  1998/06/06 23:22:21  yosh
 
50
 *   * adding Lighting plugin
 
51
 *
 
52
 *   * updated despeckle, png, sgi, and sharpen
 
53
 *
 
54
 *   -Yosh
 
55
 *
 
56
 *   Revision 1.5  1998/04/23  17:40:49  mike
 
57
 *   Updated to support 16-bit <unsigned> image data.
 
58
 *
 
59
 *   Revision 1.4  1998/02/05  17:10:58  mike
 
60
 *   Added sgiOpenFile() function for opening an existing file pointer.
 
61
 *
 
62
 *   Revision 1.3  1997/07/02  16:40:16  mike
 
63
 *   sgiOpen() wasn't opening files with "rb" or "wb+".  This caused problems
 
64
 *   on PCs running Windows/DOS...
 
65
 *
 
66
 *   Revision 1.2  1997/06/18  00:55:28  mike
 
67
 *   Updated to hold length table when writing.
 
68
 *   Updated to hold current length when doing ARLE.
 
69
 *   Wasn't writing length table on close.
 
70
 *   Wasn't saving new line into arle_row when necessary.
 
71
 *
 
72
 *   Revision 1.1  1997/06/15  03:37:19  mike
 
73
 *   Initial revision
 
74
 */
 
75
 
 
76
#include "sgi.h"
 
77
 
 
78
 
 
79
/*
 
80
 * Local functions...
 
81
 */
 
82
 
 
83
static int      getlong(sgi_t*);
 
84
static int      getshort(sgi_t*);
 
85
static int      putlong(long, sgi_t*);
 
86
static int      putshort(unsigned short, sgi_t*);
 
87
static int      read_rle8(sgi_t*, unsigned short *, int);
 
88
static int      read_rle16(sgi_t*, unsigned short *, int);
 
89
static int      write_rle8(sgi_t*, unsigned short *, int);
 
90
static int      write_rle16(sgi_t*, unsigned short *, int);
 
91
 
 
92
 
 
93
/*
 
94
 * 'sgiClose()' - Close an SGI image file.
 
95
 */
 
96
 
 
97
int
 
98
sgiClose(sgi_t *sgip)   /* I - SGI image */
 
99
{
 
100
  int   i;              /* Return status */
 
101
  long  *offset;        /* Looping var for offset table */
 
102
 
 
103
 
 
104
  if (sgip == NULL)
 
105
    return (-1);
 
106
 
 
107
  if (sgip->mode == SGI_WRITE && sgip->comp != SGI_COMP_NONE)
 
108
  {
 
109
   /*
 
110
    * Write the scanline offset table to the file...
 
111
    */
 
112
 
 
113
    fseek(sgip->file, 512, SEEK_SET);
 
114
 
 
115
    for (i = sgip->ysize * sgip->zsize, offset = sgip->table[0];
 
116
         i > 0;
 
117
         i --, offset ++)
 
118
      if (putlong(offset[0], sgip) < 0)
 
119
        return (-1);
 
120
 
 
121
    for (i = sgip->ysize * sgip->zsize, offset = sgip->length[0];
 
122
         i > 0;
 
123
         i --, offset ++)
 
124
      if (putlong(offset[0], sgip) < 0)
 
125
        return (-1);
 
126
  };
 
127
 
 
128
  if (sgip->table != NULL)
 
129
  {
 
130
    free(sgip->table[0]);
 
131
    free(sgip->table);
 
132
  };
 
133
 
 
134
  if (sgip->length != NULL)
 
135
  {
 
136
    free(sgip->length[0]);
 
137
    free(sgip->length);
 
138
  };
 
139
 
 
140
  if (sgip->comp == SGI_COMP_ARLE)
 
141
    free(sgip->arle_row);
 
142
 
 
143
  i = fclose(sgip->file);
 
144
  free(sgip);
 
145
 
 
146
  return (i);
 
147
}
 
148
 
 
149
 
 
150
/*
 
151
 * 'sgiGetRow()' - Get a row of image data from a file.
 
152
 */
 
153
 
 
154
int
 
155
sgiGetRow(sgi_t          *sgip, /* I - SGI image */
 
156
          unsigned short *row,  /* O - Row to read */
 
157
          int            y,     /* I - Line to read */
 
158
          int            z)     /* I - Channel to read */
 
159
{
 
160
  int   x;              /* X coordinate */
 
161
  long  offset;         /* File offset */
 
162
 
 
163
 
 
164
  if (sgip == NULL ||
 
165
      row == NULL ||
 
166
      y < 0 || y >= sgip->ysize ||
 
167
      z < 0 || z >= sgip->zsize)
 
168
    return (-1);
 
169
 
 
170
  switch (sgip->comp)
 
171
  {
 
172
    case SGI_COMP_NONE :
 
173
       /*
 
174
        * Seek to the image row - optimize buffering by only seeking if
 
175
        * necessary...
 
176
        */
 
177
 
 
178
        offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp;
 
179
        if (offset != ftell(sgip->file))
 
180
          fseek(sgip->file, offset, SEEK_SET);
 
181
 
 
182
        if (sgip->bpp == 1)
 
183
        {
 
184
          for (x = sgip->xsize; x > 0; x --, row ++)
 
185
            *row = getc(sgip->file);
 
186
        }
 
187
        else
 
188
        {
 
189
          for (x = sgip->xsize; x > 0; x --, row ++)
 
190
            *row = getshort(sgip);
 
191
        };
 
192
        break;
 
193
 
 
194
    case SGI_COMP_RLE :
 
195
        offset = sgip->table[z][y];
 
196
        if (offset != ftell(sgip->file))
 
197
          fseek(sgip->file, offset, SEEK_SET);
 
198
 
 
199
        if (sgip->bpp == 1)
 
200
          return (read_rle8(sgip, row, sgip->xsize));
 
201
        else
 
202
          return (read_rle16(sgip, row, sgip->xsize));
 
203
        break;
 
204
  };
 
205
 
 
206
  return (0);
 
207
}
 
208
 
 
209
 
 
210
/*
 
211
 * 'sgiOpen()' - Open an SGI image file for reading or writing.
 
212
 */
 
213
 
 
214
sgi_t *
 
215
sgiOpen(char *filename, /* I - File to open */
 
216
        int  mode,      /* I - Open mode (SGI_READ or SGI_WRITE) */
 
217
        int  comp,      /* I - Type of compression */
 
218
        int  bpp,       /* I - Bytes per pixel */
 
219
        int  xsize,     /* I - Width of image in pixels */
 
220
        int  ysize,     /* I - Height of image in pixels */
 
221
        int  zsize)     /* I - Number of channels */
 
222
{
 
223
  sgi_t *sgip;          /* New SGI image file */
 
224
  FILE  *file;          /* Image file pointer */
 
225
 
 
226
 
 
227
  if (mode == SGI_READ)
 
228
    file = fopen(filename, "rb");
 
229
  else
 
230
    file = fopen(filename, "wb+");
 
231
 
 
232
  if (file == NULL)
 
233
    return (NULL);
 
234
 
 
235
  if ((sgip = sgiOpenFile(file, mode, comp, bpp, xsize, ysize, zsize)) == NULL)
 
236
    fclose(file);
 
237
 
 
238
  return (sgip);
 
239
}
 
240
 
 
241
 
 
242
/*
 
243
 * 'sgiOpenFile()' - Open an SGI image file for reading or writing.
 
244
 */
 
245
 
 
246
sgi_t *
 
247
sgiOpenFile(FILE *file, /* I - File to open */
 
248
            int  mode,  /* I - Open mode (SGI_READ or SGI_WRITE) */
 
249
            int  comp,  /* I - Type of compression */
 
250
            int  bpp,   /* I - Bytes per pixel */
 
251
            int  xsize, /* I - Width of image in pixels */
 
252
            int  ysize, /* I - Height of image in pixels */
 
253
            int  zsize) /* I - Number of channels */
 
254
{
 
255
  int   i, j;           /* Looping var */
 
256
  char  name[80];       /* Name of file in image header */
 
257
  short magic;          /* Magic number */
 
258
  sgi_t *sgip;          /* New image pointer */
 
259
 
 
260
 
 
261
  if ((sgip = calloc(sizeof(sgi_t), 1)) == NULL)
 
262
    return (NULL);
 
263
 
 
264
  sgip->file = file;
 
265
  sgip->swapBytes = 0;
 
266
 
 
267
  switch (mode)
 
268
  {
 
269
    case SGI_READ :
 
270
        sgip->mode = SGI_READ;
 
271
 
 
272
        magic = getshort(sgip);
 
273
        if (magic != SGI_MAGIC)
 
274
        {
 
275
          /* try little endian format */
 
276
          magic = ((magic >> 8) & 0x00ff) | ((magic << 8) & 0xff00);
 
277
          if(magic != SGI_MAGIC) {
 
278
            free(sgip);
 
279
            return (NULL);
 
280
          } else {
 
281
            sgip->swapBytes = 1;
 
282
          }
 
283
        }
 
284
 
 
285
        sgip->comp  = getc(sgip->file);
 
286
        sgip->bpp   = getc(sgip->file);
 
287
        getshort(sgip);         /* Dimensions */
 
288
        sgip->xsize = getshort(sgip);
 
289
        sgip->ysize = getshort(sgip);
 
290
        sgip->zsize = getshort(sgip);
 
291
        getlong(sgip);          /* Minimum pixel */
 
292
        getlong(sgip);          /* Maximum pixel */
 
293
 
 
294
        if (sgip->comp)
 
295
        {
 
296
         /*
 
297
          * This file is compressed; read the scanline tables...
 
298
          */
 
299
 
 
300
          fseek(sgip->file, 512, SEEK_SET);
 
301
 
 
302
          sgip->table    = calloc(sgip->zsize, sizeof(long *));
 
303
          sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long));
 
304
          for (i = 1; i < sgip->zsize; i ++)
 
305
            sgip->table[i] = sgip->table[0] + i * sgip->ysize;
 
306
 
 
307
          for (i = 0; i < sgip->zsize; i ++)
 
308
            for (j = 0; j < sgip->ysize; j ++)
 
309
              sgip->table[i][j] = getlong(sgip);
 
310
        };
 
311
        break;
 
312
 
 
313
    case SGI_WRITE :
 
314
        if (xsize < 1 ||
 
315
            ysize < 1 ||
 
316
            zsize < 1 ||
 
317
            bpp < 1 || bpp > 2 ||
 
318
            comp < SGI_COMP_NONE || comp > SGI_COMP_ARLE)
 
319
        {
 
320
          free(sgip);
 
321
          return (NULL);
 
322
        };
 
323
 
 
324
        sgip->mode = SGI_WRITE;
 
325
 
 
326
        putshort(SGI_MAGIC, sgip);
 
327
        putc((sgip->comp = comp) != 0, sgip->file);
 
328
        putc(sgip->bpp = bpp, sgip->file);
 
329
        putshort(3, sgip);              /* Dimensions */
 
330
        putshort(sgip->xsize = xsize, sgip);
 
331
        putshort(sgip->ysize = ysize, sgip);
 
332
        putshort(sgip->zsize = zsize, sgip);
 
333
        if (bpp == 1)
 
334
        {
 
335
          putlong(0, sgip);     /* Minimum pixel */
 
336
          putlong(255, sgip);   /* Maximum pixel */
 
337
        }
 
338
        else
 
339
        {
 
340
          putlong(-32768, sgip);        /* Minimum pixel */
 
341
          putlong(32767, sgip); /* Maximum pixel */
 
342
        };
 
343
        putlong(0, sgip);               /* Reserved */
 
344
 
 
345
        memset(name, 0, sizeof(name));
 
346
        fwrite(name, sizeof(name), 1, sgip->file);
 
347
 
 
348
        for (i = 0; i < 102; i ++)
 
349
          putlong(0, sgip);
 
350
 
 
351
        switch (comp)
 
352
        {
 
353
          case SGI_COMP_NONE : /* No compression */
 
354
             /*
 
355
              * This file is uncompressed.  To avoid problems with sparse files,
 
356
              * we need to write blank pixels for the entire image...
 
357
              */
 
358
 
 
359
              if (bpp == 1)
 
360
              {
 
361
                for (i = xsize * ysize * zsize; i > 0; i --)
 
362
                  putc(0, sgip->file);
 
363
              }
 
364
              else
 
365
              {
 
366
                for (i = xsize * ysize * zsize; i > 0; i --)
 
367
                  putshort(0, sgip);
 
368
              };
 
369
              break;
 
370
 
 
371
          case SGI_COMP_ARLE : /* Aggressive RLE */
 
372
              sgip->arle_row    = (unsigned short *)calloc(xsize, sizeof(unsigned short));
 
373
              sgip->arle_offset = 0;
 
374
 
 
375
          case SGI_COMP_RLE : /* Run-Length Encoding */
 
376
             /*
 
377
              * This file is compressed; write the (blank) scanline tables...
 
378
              */
 
379
 
 
380
              for (i = 2 * ysize * zsize; i > 0; i --)
 
381
                putlong(0, sgip);
 
382
 
 
383
              sgip->firstrow = ftell(sgip->file);
 
384
              sgip->nextrow  = ftell(sgip->file);
 
385
              sgip->table    = calloc(sgip->zsize, sizeof(long *));
 
386
              sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long));
 
387
              for (i = 1; i < sgip->zsize; i ++)
 
388
                sgip->table[i] = sgip->table[0] + i * sgip->ysize;
 
389
              sgip->length    = calloc(sgip->zsize, sizeof(long *));
 
390
              sgip->length[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long));
 
391
              for (i = 1; i < sgip->zsize; i ++)
 
392
                sgip->length[i] = sgip->length[0] + i * sgip->ysize;
 
393
              break;
 
394
        };
 
395
        break;
 
396
 
 
397
    default :
 
398
        free(sgip);
 
399
        return (NULL);
 
400
  };
 
401
 
 
402
  return (sgip);
 
403
}
 
404
 
 
405
 
 
406
/*
 
407
 * 'sgiPutRow()' - Put a row of image data to a file.
 
408
 */
 
409
 
 
410
int
 
411
sgiPutRow(sgi_t          *sgip, /* I - SGI image */
 
412
          unsigned short *row,  /* I - Row to write */
 
413
          int            y,     /* I - Line to write */
 
414
          int            z)     /* I - Channel to write */
 
415
{
 
416
  int   x;              /* X coordinate */
 
417
  long  offset;         /* File offset */
 
418
 
 
419
 
 
420
  if (sgip == NULL ||
 
421
      row == NULL ||
 
422
      y < 0 || y >= sgip->ysize ||
 
423
      z < 0 || z >= sgip->zsize)
 
424
    return (-1);
 
425
 
 
426
  switch (sgip->comp)
 
427
  {
 
428
    case SGI_COMP_NONE :
 
429
       /*
 
430
        * Seek to the image row - optimize buffering by only seeking if
 
431
        * necessary...
 
432
        */
 
433
 
 
434
        offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp;
 
435
        if (offset != ftell(sgip->file))
 
436
          fseek(sgip->file, offset, SEEK_SET);
 
437
 
 
438
        if (sgip->bpp == 1)
 
439
        {
 
440
          for (x = sgip->xsize; x > 0; x --, row ++)
 
441
            putc(*row, sgip->file);
 
442
        }
 
443
        else
 
444
        {
 
445
          for (x = sgip->xsize; x > 0; x --, row ++)
 
446
            putshort(*row, sgip);
 
447
        };
 
448
        break;
 
449
 
 
450
    case SGI_COMP_ARLE :
 
451
        if (sgip->table[z][y] != 0)
 
452
          return (-1);
 
453
 
 
454
       /*
 
455
        * First check the last row written...
 
456
        */
 
457
 
 
458
        if (sgip->arle_offset > 0)
 
459
        {
 
460
          for (x = 0; x < sgip->xsize; x ++)
 
461
            if (row[x] != sgip->arle_row[x])
 
462
              break;
 
463
 
 
464
          if (x == sgip->xsize)
 
465
          {
 
466
            sgip->table[z][y]  = sgip->arle_offset;
 
467
            sgip->length[z][y] = sgip->arle_length;
 
468
            return (0);
 
469
          };
 
470
        };
 
471
 
 
472
       /*
 
473
        * If that didn't match, search all the previous rows...
 
474
        */
 
475
 
 
476
        fseek(sgip->file, sgip->firstrow, SEEK_SET);
 
477
 
 
478
        if (sgip->bpp == 1)
 
479
        {
 
480
          do
 
481
          {
 
482
            sgip->arle_offset = ftell(sgip->file);
 
483
            if ((sgip->arle_length = read_rle8(sgip, sgip->arle_row, sgip->xsize)) < 0)
 
484
            {
 
485
              x = 0;
 
486
              break;
 
487
            };
 
488
 
 
489
            for (x = 0; x < sgip->xsize; x ++)
 
490
              if (row[x] != sgip->arle_row[x])
 
491
                break;
 
492
          }
 
493
          while (x < sgip->xsize);
 
494
        }
 
495
        else
 
496
        {
 
497
          do
 
498
          {
 
499
            sgip->arle_offset = ftell(sgip->file);
 
500
            if ((sgip->arle_length = read_rle16(sgip, sgip->arle_row, sgip->xsize)) < 0)
 
501
            {
 
502
              x = 0;
 
503
              break;
 
504
            };
 
505
 
 
506
            for (x = 0; x < sgip->xsize; x ++)
 
507
              if (row[x] != sgip->arle_row[x])
 
508
                break;
 
509
          }
 
510
          while (x < sgip->xsize);
 
511
        };
 
512
 
 
513
        if (x == sgip->xsize)
 
514
        {
 
515
          sgip->table[z][y]  = sgip->arle_offset;
 
516
          sgip->length[z][y] = sgip->arle_length;
 
517
          return (0);
 
518
        }
 
519
        else
 
520
          fseek(sgip->file, 0, SEEK_END);       /* Clear EOF */
 
521
 
 
522
    case SGI_COMP_RLE :
 
523
        if (sgip->table[z][y] != 0)
 
524
          return (-1);
 
525
 
 
526
        offset = sgip->table[z][y] = sgip->nextrow;
 
527
 
 
528
        if (offset != ftell(sgip->file))
 
529
          fseek(sgip->file, offset, SEEK_SET);
 
530
 
 
531
        if (sgip->bpp == 1)
 
532
          x = write_rle8(sgip, row, sgip->xsize);
 
533
        else
 
534
          x = write_rle16(sgip, row, sgip->xsize);
 
535
 
 
536
        if (sgip->comp == SGI_COMP_ARLE)
 
537
        {
 
538
          sgip->arle_offset = offset;
 
539
          sgip->arle_length = x;
 
540
          memcpy(sgip->arle_row, row, sgip->xsize * sizeof(short));
 
541
        };
 
542
 
 
543
        sgip->nextrow      = ftell(sgip->file);
 
544
        sgip->length[z][y] = x;
 
545
 
 
546
        return (x);
 
547
  };
 
548
 
 
549
  return (0);
 
550
}
 
551
 
 
552
 
 
553
/*
 
554
 * 'getlong()' - Get a 32-bit big-endian integer.
 
555
 */
 
556
 
 
557
static int
 
558
getlong(sgi_t *sgip)    /* I - SGI image to read from */
 
559
{
 
560
  unsigned char b[4];
 
561
 
 
562
 
 
563
  fread(b, 4, 1, sgip->file);
 
564
  if(sgip->swapBytes)
 
565
    return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]);
 
566
  else
 
567
    return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]);
 
568
}
 
569
 
 
570
 
 
571
/*
 
572
 * 'getshort()' - Get a 16-bit big-endian integer.
 
573
 */
 
574
 
 
575
static int
 
576
getshort(sgi_t *sgip)   /* I - SGI image to read from */
 
577
{
 
578
  unsigned char b[2];
 
579
 
 
580
 
 
581
  fread(b, 2, 1, sgip->file);
 
582
  if(sgip->swapBytes)
 
583
    return ((b[1] << 8) | b[0]);
 
584
  else
 
585
    return ((b[0] << 8) | b[1]);
 
586
}
 
587
 
 
588
 
 
589
/*
 
590
 * 'putlong()' - Put a 32-bit big-endian integer.
 
591
 */
 
592
 
 
593
static int
 
594
putlong(long n,         /* I - Long to write */
 
595
        sgi_t *sgip)    /* I - File to write to */
 
596
{
 
597
  if (putc(n >> 24, sgip->file) == EOF)
 
598
    return (EOF);
 
599
  if (putc(n >> 16, sgip->file) == EOF)
 
600
    return (EOF);
 
601
  if (putc(n >> 8, sgip->file) == EOF)
 
602
    return (EOF);
 
603
  if (putc(n, sgip->file) == EOF)
 
604
    return (EOF);
 
605
  else
 
606
    return (0);
 
607
}
 
608
 
 
609
 
 
610
/*
 
611
 * 'putshort()' - Put a 16-bit big-endian integer.
 
612
 */
 
613
 
 
614
static int
 
615
putshort(unsigned short n,      /* I - Short to write */
 
616
         sgi_t *sgip)           /* I - File to write to */
 
617
{
 
618
  if (putc(n >> 8, sgip->file) == EOF)
 
619
    return (EOF);
 
620
  if (putc(n, sgip->file) == EOF)
 
621
    return (EOF);
 
622
  else
 
623
    return (0);
 
624
}
 
625
 
 
626
 
 
627
/*
 
628
 * 'read_rle8()' - Read 8-bit RLE data.
 
629
 */
 
630
 
 
631
static int
 
632
read_rle8(sgi_t *sgip,          /* I - SGI image to read from */
 
633
          unsigned short *row,  /* O - Data */
 
634
          int            xsize) /* I - Width of data in pixels */
 
635
{
 
636
  int   i,              /* Looping var */
 
637
        ch,             /* Current character */
 
638
        count,          /* RLE count */
 
639
        length;         /* Number of bytes read... */
 
640
 
 
641
 
 
642
  length = 0;
 
643
 
 
644
  while (xsize > 0)
 
645
  {
 
646
    if ((ch = getc(sgip->file)) == EOF)
 
647
      return (-1);
 
648
    length ++;
 
649
 
 
650
    count = ch & 127;
 
651
    if (count == 0)
 
652
      break;
 
653
 
 
654
    if (ch & 128)
 
655
    {
 
656
      for (i = 0; i < count; i ++, row ++, xsize --, length ++)
 
657
        *row = getc(sgip->file);
 
658
    }
 
659
    else
 
660
    {
 
661
      ch = getc(sgip->file);
 
662
      length ++;
 
663
      for (i = 0; i < count; i ++, row ++, xsize --)
 
664
        *row = ch;
 
665
    };
 
666
  };
 
667
 
 
668
  return (xsize > 0 ? -1 : length);
 
669
}
 
670
 
 
671
 
 
672
/*
 
673
 * 'read_rle16()' - Read 16-bit RLE data.
 
674
 */
 
675
 
 
676
static int
 
677
read_rle16(sgi_t *sgip,         /* I - SGI image to read from */
 
678
           unsigned short *row, /* O - Data */
 
679
           int            xsize)/* I - Width of data in pixels */
 
680
{
 
681
  int   i,              /* Looping var */
 
682
        ch,             /* Current character */
 
683
        count,          /* RLE count */
 
684
        length;         /* Number of bytes read... */
 
685
 
 
686
 
 
687
  length = 0;
 
688
 
 
689
  while (xsize > 0)
 
690
  {
 
691
    if ((ch = getshort(sgip)) == EOF)
 
692
      return (-1);
 
693
    length ++;
 
694
 
 
695
    count = ch & 127;
 
696
    if (count == 0)
 
697
      break;
 
698
 
 
699
    if (ch & 128)
 
700
    {
 
701
      for (i = 0; i < count; i ++, row ++, xsize --, length ++)
 
702
        *row = getshort(sgip);
 
703
    }
 
704
    else
 
705
    {
 
706
      ch = getshort(sgip);
 
707
      length ++;
 
708
      for (i = 0; i < count; i ++, row ++, xsize --)
 
709
        *row = ch;
 
710
    };
 
711
  };
 
712
 
 
713
  return (xsize > 0 ? -1 : length * 2);
 
714
}
 
715
 
 
716
 
 
717
/*
 
718
 * 'write_rle8()' - Write 8-bit RLE data.
 
719
 */
 
720
 
 
721
static int
 
722
write_rle8(sgi_t *sgip,         /* I - SGI image to write to */
 
723
           unsigned short *row, /* I - Data */
 
724
           int            xsize)/* I - Width of data in pixels */
 
725
{
 
726
  int                   length, /* Length of output line */
 
727
                        count,  /* Number of repeated/non-repeated pixels */
 
728
                        i,      /* Looping var */
 
729
                        x;      /* Looping var */
 
730
  unsigned short        *start, /* Start of sequence */
 
731
                        repeat; /* Repeated pixel */
 
732
 
 
733
 
 
734
  for (x = xsize, length = 0; x > 0;)
 
735
  {
 
736
    start = row;
 
737
    row   += 2;
 
738
    x     -= 2;
 
739
 
 
740
    while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0]))
 
741
    {
 
742
      row ++;
 
743
      x --;
 
744
    };
 
745
 
 
746
    row -= 2;
 
747
    x   += 2;
 
748
 
 
749
    count = row - start;
 
750
    while (count > 0)
 
751
    {
 
752
      i     = count > 126 ? 126 : count;
 
753
      count -= i;
 
754
 
 
755
      if (putc(128 | i, sgip->file) == EOF)
 
756
        return (-1);
 
757
      length ++;
 
758
 
 
759
      while (i > 0)
 
760
      {
 
761
        if (putc(*start, sgip->file) == EOF)
 
762
          return (-1);
 
763
        start ++;
 
764
        i --;
 
765
        length ++;
 
766
      };
 
767
    };
 
768
 
 
769
    if (x <= 0)
 
770
      break;
 
771
 
 
772
    start  = row;
 
773
    repeat = row[0];
 
774
 
 
775
    row ++;
 
776
    x --;
 
777
 
 
778
    while (x > 0 && *row == repeat)
 
779
    {
 
780
      row ++;
 
781
      x --;
 
782
    };
 
783
 
 
784
    count = row - start;
 
785
    while (count > 0)
 
786
    {
 
787
      i     = count > 126 ? 126 : count;
 
788
      count -= i;
 
789
 
 
790
      if (putc(i, sgip->file) == EOF)
 
791
        return (-1);
 
792
      length ++;
 
793
 
 
794
      if (putc(repeat, sgip->file) == EOF)
 
795
        return (-1);
 
796
      length ++;
 
797
    };
 
798
  };
 
799
 
 
800
  length ++;
 
801
 
 
802
  if (putc(0, sgip->file) == EOF)
 
803
    return (-1);
 
804
  else
 
805
    return (length);
 
806
}
 
807
 
 
808
 
 
809
/*
 
810
 * 'write_rle16()' - Write 16-bit RLE data.
 
811
 */
 
812
 
 
813
static int
 
814
write_rle16(sgi_t *sgip,        /* I - SGI image to write to */
 
815
            unsigned short *row,/* I - Data */
 
816
            int            xsize)/* I - Width of data in pixels */
 
817
{
 
818
  int                   length, /* Length of output line */
 
819
                        count,  /* Number of repeated/non-repeated pixels */
 
820
                        i,      /* Looping var */
 
821
                        x;      /* Looping var */
 
822
  unsigned short        *start, /* Start of sequence */
 
823
                        repeat; /* Repeated pixel */
 
824
 
 
825
 
 
826
  for (x = xsize, length = 0; x > 0;)
 
827
  {
 
828
    start = row;
 
829
    row   += 2;
 
830
    x     -= 2;
 
831
 
 
832
    while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0]))
 
833
    {
 
834
      row ++;
 
835
      x --;
 
836
    };
 
837
 
 
838
    row -= 2;
 
839
    x   += 2;
 
840
 
 
841
    count = row - start;
 
842
    while (count > 0)
 
843
    {
 
844
      i     = count > 126 ? 126 : count;
 
845
      count -= i;
 
846
 
 
847
      if (putshort(128 | i, sgip) == EOF)
 
848
        return (-1);
 
849
      length ++;
 
850
 
 
851
      while (i > 0)
 
852
      {
 
853
        if (putshort(*start, sgip) == EOF)
 
854
          return (-1);
 
855
        start ++;
 
856
        i --;
 
857
        length ++;
 
858
      };
 
859
    };
 
860
 
 
861
    if (x <= 0)
 
862
      break;
 
863
 
 
864
    start  = row;
 
865
    repeat = row[0];
 
866
 
 
867
    row ++;
 
868
    x --;
 
869
 
 
870
    while (x > 0 && *row == repeat)
 
871
    {
 
872
      row ++;
 
873
      x --;
 
874
    };
 
875
 
 
876
    count = row - start;
 
877
    while (count > 0)
 
878
    {
 
879
      i     = count > 126 ? 126 : count;
 
880
      count -= i;
 
881
 
 
882
      if (putshort(i, sgip) == EOF)
 
883
        return (-1);
 
884
      length ++;
 
885
 
 
886
      if (putshort(repeat, sgip) == EOF)
 
887
        return (-1);
 
888
      length ++;
 
889
    };
 
890
  };
 
891
 
 
892
  length ++;
 
893
 
 
894
  if (putshort(0, sgip) == EOF)
 
895
    return (-1);
 
896
  else
 
897
    return (2 * length);
 
898
}
 
899
 
 
900
 
 
901
/*
 
902
 * End of "$Id: sgilib.c,v 1.8 2003/04/07 11:59:33 neo Exp $".
 
903
 */