home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / sgi / sgilib.c < prev   
Encoding:
C/C++ Source or Header  |  1998-06-06  |  20.8 KB  |  883 lines

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