home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / rad386 / radiosit / src / for_rle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-24  |  32.0 KB  |  1,183 lines

  1. /*
  2.  * This software is copyrighted as noted below.  It may be freely copied,
  3.  * modified, and redistributed, provided that the copyright notice is 
  4.  * preserved on all copies.
  5.  * 
  6.  * There is no warranty or other guarantee of fitness for this software,
  7.  * it is provided solely "as is".  Bug reports or fixes may be sent
  8.  * to the author, who may or may not act on them as he desires.
  9.  *
  10.  * You may not include this software in a program or other software product
  11.  * without supplying the source, or without informing the end-user that the 
  12.  * source is available for no extra charge.
  13.  *
  14.  * If you modify this software, you should include a notice giving the
  15.  * name of the person performing the modification, the date of modification,
  16.  * and the reason for such modification.
  17.  *
  18.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  19.  *  to have all "void" functions so declared.
  20.  */
  21. /* 
  22.  * rle_row_alc.c - Allocate buffers for rle_getrow/rle_putrow.
  23.  * 
  24.  * Author:    Spencer W. Thomas
  25.  *         Computer Science Dept.
  26.  *         University of Utah
  27.  * Date:    Fri Nov 14 1986
  28.  * Copyright (c) 1986, Spencer W. Thomas
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <malloc.h>
  33. #include "rle_put.h"
  34.  
  35. #include "raddecl.h"
  36.  
  37. /*****************************************************************
  38.  * TAG( rle_row_alloc )
  39.  * 
  40.  * Allocate buffer space for use by rle_getrow and rle_putrow.
  41.  * Inputs:
  42.  *     the_hdr:    Header structure for RLE file to be read or
  43.  *            written.
  44.  * Outputs:
  45.  *    scanp:        Pointer to pointer to created scanline buffer.
  46.  *            This pointer is adjusted for the alpha channel,
  47.  *            if present.
  48.  *    Returns 0 for success, -1 if malloc failed.
  49.  * Assumptions:
  50.  *     No input scanline will extend beyond the declared xmax endpoint.
  51.  * Algorithm:
  52.  *    Count number of channels actually used (check bitmap).
  53.  *     Allocate nchan*rowlength pixels, allocate a buffer
  54.  *    to hold ncolors+alpha pointers, and give each channel
  55.  *    rowlength pixels.  Rowlength is xmax + 1, to allow for rle_getrow
  56.  *    usage.
  57.  */
  58. int rle_row_alloc( the_hdr, scanp )
  59. rle_hdr *the_hdr;
  60. rle_pixel ***scanp;
  61. {
  62.     rle_pixel ** scanbuf, * pixbuf;
  63.     int rowlen, nchan = 0, i, ncol;
  64.  
  65.     rowlen = the_hdr->xmax + 1;
  66.     if ( the_hdr->alpha && RLE_BIT( *the_hdr, RLE_ALPHA ) )
  67.     nchan++;
  68.     for ( i = 0; i < the_hdr->ncolors; i++ )
  69.     if ( RLE_BIT( *the_hdr, i ) )
  70.          nchan++;
  71.  
  72.     ncol = the_hdr->ncolors + the_hdr->alpha;
  73.  
  74.     if ( (scanbuf = (rle_pixel **)malloc( ncol * sizeof(rle_pixel *) )) == 0 )
  75.     return -1;
  76.     if ( (pixbuf = (rle_pixel *)malloc( nchan * rowlen *
  77.                        sizeof(rle_pixel) )) == 0 )
  78.     {
  79.     free( scanbuf );
  80.     return -1;
  81.     }
  82.  
  83.     if ( the_hdr->alpha )
  84.     scanbuf++;
  85.  
  86.     for ( i = -the_hdr->alpha; i < the_hdr->ncolors; i++ )
  87.     if ( RLE_BIT( *the_hdr, i ) )
  88.     {
  89.         scanbuf[i] = pixbuf;
  90.         pixbuf += rowlen;
  91.     }
  92.     else
  93.         scanbuf[i] = 0;
  94.     *scanp = scanbuf;
  95.  
  96.     return 0;
  97. }
  98.  
  99.  
  100. /*****************************************************************
  101.  * TAG( rle_row_free )
  102.  * 
  103.  * Free storage allocated by rle_row_alloc().
  104.  * Inputs:
  105.  *     the_hdr:    Header structure as above.
  106.  *    scanp:        Pointer to scanbuf above.
  107.  * Outputs:
  108.  *     Frees storage referenced by scanp and nrawp.
  109.  * Assumptions:
  110.  *     Storage was allocated by rle_row_alloc, or by use of same
  111.  *    algorithm, at least.
  112.  * Algorithm:
  113.  *     free scanp[0] and scanp.
  114.  */
  115. void rle_row_free( the_hdr, scanp )
  116. rle_hdr *the_hdr;
  117. rle_pixel **scanp;
  118. {
  119.     int i;
  120.  
  121.     if ( the_hdr->alpha )
  122.     scanp--;
  123.     for ( i = 0; i < the_hdr->ncolors + the_hdr->alpha; i++ )
  124.     if ( scanp[i] != 0 )
  125.     {
  126.         free( (char *)scanp[i] );
  127.         break;
  128.     }
  129.     free( (char *)scanp );
  130. }
  131. /*
  132.  * This software is copyrighted as noted below.  It may be freely copied,
  133.  * modified, and redistributed, provided that the copyright notice is 
  134.  * preserved on all copies.
  135.  * 
  136.  * There is no warranty or other guarantee of fitness for this software,
  137.  * it is provided solely "as is".  Bug reports or fixes may be sent
  138.  * to the author, who may or may not act on them as he desires.
  139.  *
  140.  * You may not include this software in a program or other software product
  141.  * without supplying the source, or without informing the end-user that the 
  142.  * source is available for no extra charge.
  143.  *
  144.  * If you modify this software, you should include a notice giving the
  145.  * name of the person performing the modification, the date of modification,
  146.  * and the reason for such modification.
  147.  *
  148.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  149.  *  to have all "void" functions so declared.
  150.  */
  151. /* 
  152.  * rle_putrow.c - Save a row of the fb to a file.
  153.  * 
  154.  * Author:    Spencer W. Thomas
  155.  *         Computer Science Dept.
  156.  *         University of Utah
  157.  * Date:    1 April 1981
  158.  * Copyright (c) 1981,1986 Spencer W. Thomas
  159.  *
  160.  * $Id: rle_putrow.c,v 3.0.1.1 90/11/27 14:54:37 spencer Exp $
  161.  */
  162.  
  163. #ifdef USE_STDLIB_H
  164. #include <stdlib.h>
  165. #else
  166.  
  167. #endif /* USE_STDLIB_H */
  168.  
  169. static int findruns();
  170.  
  171. #define FASTRUNS        /* Faster run finding */
  172. #ifdef vax
  173. #define LOCC            /* Use vax instructions for more speed */
  174. #endif
  175.  
  176. #define    FALSE    0
  177. #define    TRUE    1
  178.  
  179. /*****************************************************************
  180.  * TAG( rle_putrow )
  181.  * Write a scanline to the output file.
  182.  * 
  183.  * Inputs:
  184.  *    rows:        Pointer to vector of pointers to
  185.  *            rle_pixel arrays containing the pixel information.
  186.  *            If NULL, rowlen scanlines are skipped.
  187.  *    rowlen:        The number of pixels in the scanline, or the
  188.  *            number of scanlines to skip (see above).
  189.  * Outputs:
  190.  *     Run length encoded information is written to the_hdr.rle_file.
  191.  * Assumptions:
  192.  *     I'm sure there are lots of assumptions in here.
  193.  * Algorithm:
  194.  *     [read the code :-]
  195.  */
  196.  
  197. void rle_putrow(rows, rowlen, the_hdr)
  198. register rle_pixel *rows[];
  199. int rowlen;
  200. register rle_hdr * the_hdr;
  201. {
  202.     register int i, j;
  203.     int nrun;
  204.     register rle_pixel *row;
  205.     int mask;
  206.     char bits[256];
  207.     short   state,
  208.         dstart,
  209.             dend,
  210.         rstart = 0,
  211.         runval = 0;            /* shut up lint */
  212.  
  213.     if (rows == NULL)
  214.     {
  215.     the_hdr->priv.put.nblank += rowlen;
  216.     return;
  217.     }
  218.     /* 
  219.      * If not done already, allocate space to remember runs of
  220.      * non-background color.  A run of bg color must be at least 2
  221.      * bytes long to count, so there can be at most rowlen/3 of them.
  222.      */
  223.     if ( the_hdr->priv.put.brun == NULL )
  224.     {
  225.     the_hdr->priv.put.brun =
  226.         (short (*)[2])malloc(
  227.         (unsigned)((rowlen/3 + 1) * 2 * sizeof(short)) );
  228.     if ( the_hdr->priv.put.brun == NULL )
  229.     {
  230.         fprintf( stderr, "Malloc failed in rle_putrow\n" );
  231.         exit(1);
  232.     }
  233.     }
  234.     /* Unpack bitmask in the_hdr struct */
  235.     for ( i=0; i < the_hdr->ncolors; i++ )
  236.     bits[i] = RLE_BIT( *the_hdr, i );
  237.     bits[255] = RLE_BIT( *the_hdr, -1 );
  238.  
  239.     /* 
  240.      * If saving only non-background pixels, find runs of them.  Note
  241.      * that the alpha channel is considered to be background iff it is
  242.      * zero.
  243.      */
  244. #ifdef    FASTRUNS
  245.     if ( the_hdr->background )
  246.     {
  247.     /* 
  248.      * Find runs in each color individually, merging them as we go.
  249.      */
  250.     nrun = 0;        /* start out with no runs */
  251.     /* Alpha channel first */
  252.     if ( the_hdr->alpha )
  253.         nrun = findruns( rows[-1], rowlen, 0, nrun,
  254.                 the_hdr->priv.put.brun );
  255.     /* Now the color channels */
  256.     for ( i = 0; i < the_hdr->ncolors; i++ )
  257.         if ( bits[i] )
  258.         nrun = findruns( rows[i], rowlen, the_hdr->bg_color[i],
  259.                  nrun, the_hdr->priv.put.brun );
  260.     }
  261.     else
  262.     {
  263.     the_hdr->priv.put.brun[0][0] = 0;
  264.     the_hdr->priv.put.brun[0][1] = rowlen-1;
  265.     nrun = 1;
  266.     }
  267. #else                /* FASTRUNS */
  268.     if (the_hdr->background)    /* find non-background runs */
  269.     {
  270.     j = 0;
  271.     for (i=0; i<rowlen; i++)
  272.         if (!same_color( i, rows, the_hdr->bg_color,
  273.                  the_hdr->ncolors, bits ) ||
  274.         (the_hdr->alpha && rows[-1][i] != 0))
  275.         {
  276.         if (j > 0 && i - the_hdr->priv.put.brun[j-1][1] <= 4)
  277.             j--;
  278.         else
  279.             the_hdr->priv.put.brun[j][0] = i; /* start of run */
  280.         for ( i++;
  281.               i < rowlen && 
  282.             ( !same_color( i, rows, the_hdr->bg_color,
  283.                      the_hdr->ncolors, bits ) ||
  284.               (the_hdr->alpha && rows[-1][i] != 0) );
  285.               i++)
  286.             ;            /* find the end of this run */
  287.         the_hdr->priv.put.brun[j][1] = i-1;    /* last in run */
  288.         j++;
  289.         }
  290.     nrun = j;
  291.     }
  292.     else
  293.     {
  294.     the_hdr->priv.put.brun[0][0] = 0;
  295.     the_hdr->priv.put.brun[0][1] = rowlen-1;
  296.     nrun = 1;
  297.     }
  298. #endif                /* FASTRUNS */
  299.     if (nrun > 0)
  300.     {
  301.     if (the_hdr->priv.put.nblank > 0)
  302.     {
  303.         SkipBlankLines(the_hdr->priv.put.nblank);
  304.         the_hdr->priv.put.nblank = 0;
  305.     }
  306.     for ( mask = (the_hdr->alpha ? -1 : 0);
  307.           mask < the_hdr->ncolors;
  308.           mask++)            /* do all colors */
  309.     {
  310.         if ( ! bits[mask & 0xff] )
  311.         {
  312.         continue;
  313.         }
  314.         row = rows[mask];
  315.         SetColor(mask);
  316.         if (the_hdr->priv.put.brun[0][0] > 0)
  317.         {
  318.         SkipPixels(the_hdr->priv.put.brun[0][0], FALSE, FALSE);
  319.         }
  320.         for (j=0; j<nrun; j++)
  321.         {
  322.         state = DATA;
  323.         dstart = the_hdr->priv.put.brun[j][0];
  324.         dend = the_hdr->priv.put.brun[j][1];
  325.         for (i=dstart; i<=dend; i++)
  326.         {
  327.             switch(state)
  328.             {
  329.             case DATA:
  330.             if (i > dstart && runval == row[i])
  331.             {
  332.                 state = RUN2;    /* 2 in a row, may be a run */
  333.             }
  334.             else
  335.             {
  336.                 runval = row[i];    /* maybe a run starts here? */
  337.                 rstart = i;
  338.             }
  339.             break;
  340.         
  341.             case RUN2:
  342.             if (runval == row[i])
  343.             {
  344.                 state  = RUN3;    /* 3 in a row may be a run */
  345.             }
  346.             else
  347.             {
  348.                 state = DATA;    /* Nope, back to data */
  349.                 runval = row[i];    /* but maybe a new run here? */
  350.                 rstart = i;
  351.             }
  352.             break;
  353.  
  354.             case RUN3:
  355.             if (runval == row[i])    /* 3 in a row is a run */
  356.             {
  357.                 state = INRUN;
  358.                 putdata(row + dstart, rstart - dstart);
  359. #ifdef FASTRUNS
  360. #ifdef LOCC
  361.                 /* Shortcut to find end of run! */
  362.                 i = dend - skpc( (char *)row + i, dend + 1 - i,
  363.                          runval );
  364. #else
  365.                 while ( row[++i] == runval && i <= dend)
  366.                 ; /* not quite so good, but not bad */
  367.                 i--;
  368. #endif /* LOCC */
  369. #endif /* FASTRUNS */
  370.             }
  371.             else
  372.             {
  373.                 state = DATA;        /* not a run, */
  374.                 runval = row[i];    /* but may this starts one */
  375.                 rstart = i;
  376.             }
  377.             break;
  378.         
  379.             case INRUN:
  380.             if (runval != row[i])    /* if run out */
  381.             {
  382.                 state = DATA;
  383.                 putrun(runval, i - rstart, FALSE);
  384.                 runval = row[i];    /* who knows, might be more */
  385.                 rstart = i;
  386.                 dstart = i;    /* starting a new 'data' run */
  387.             }
  388.             break;
  389.             }
  390.         }
  391.         if (state == INRUN)
  392.             putrun(runval, i - rstart, TRUE);    /* last bit */
  393.         else
  394.             putdata(row + dstart, i - dstart);
  395.  
  396.         if (j < nrun-1)
  397.             SkipPixels(
  398.                 the_hdr->priv.put.brun[j+1][0] - dend - 1,
  399.                 FALSE, state == INRUN);
  400.         else
  401.         {
  402.             if (rowlen - dend > 0)
  403.             SkipPixels(
  404.                 rowlen - dend - 1,
  405.                 TRUE, state == INRUN);
  406.         }
  407.         }
  408.  
  409.         if ( mask != the_hdr->ncolors - 1 )
  410.         NewScanLine(FALSE);
  411.     }
  412.     }
  413.  
  414.     /* Increment to next scanline */
  415.     the_hdr->priv.put.nblank++;
  416.  
  417.     /* flush every scanline */
  418.     fflush( the_hdr->rle_file );
  419. }
  420.  
  421. /*****************************************************************
  422.  * TAG( rle_put_init )
  423.  * 
  424.  * Initialize the header structure for writing scanlines. 
  425.  * Inputs:
  426.  *    [None]
  427.  * Outputs:
  428.  *     the_hdr:    Private portions initialized for output.
  429.  * Assumptions:
  430.  *    [None]
  431.  * Algorithm:
  432.  *    [None]
  433.  */
  434. void rle_put_init( the_hdr )
  435. register rle_hdr *the_hdr;
  436. {
  437.     the_hdr->dispatch = RUN_DISPATCH;
  438.     the_hdr->priv.put.nblank = 0;    /* Reinit static vars */
  439.     /* Would like to be able to free previously allocated storage,
  440.      * but can't count on a non-NULL value being a valid pointer.
  441.      */
  442.     the_hdr->priv.put.brun = NULL;
  443.     the_hdr->priv.put.fileptr = 0;
  444.  
  445.     /* Only save alpha if alpha AND alpha channel bit are set. */
  446.     if ( the_hdr->alpha )
  447.     the_hdr->alpha = (RLE_BIT( *the_hdr, -1 ) != 0);
  448.     else
  449.     RLE_CLR_BIT( *the_hdr, -1 );
  450. }
  451.  
  452. /*****************************************************************
  453.  * TAG( rle_put_setup )
  454.  * 
  455.  * Initialize for writing RLE, and write header to output file.
  456.  * Inputs:
  457.  *     the_hdr:    Describes output image.
  458.  * Outputs:
  459.  *     the_hdr:    Initialized.
  460.  * Assumptions:
  461.  *    Lots of them.
  462.  * Algorithm:
  463.  *    [None]
  464.  */
  465. void rle_put_setup( the_hdr )
  466. register rle_hdr * the_hdr;
  467. {
  468.     rle_put_init( the_hdr );
  469.     Setup();
  470. }
  471.  
  472. /*ARGSUSED*/
  473. int DefaultBlockHook(the_hdr)
  474. rle_hdr * the_hdr;
  475. {
  476.                         /* Do nothing */
  477. }
  478.  
  479. /*****************************************************************
  480.  * TAG( rle_puteof )
  481.  * Write an EOF code into the output file.
  482.  */
  483. void rle_puteof( the_hdr )
  484. register rle_hdr * the_hdr;
  485. {
  486.     /* Don't puteof twice. */
  487.     if ( the_hdr->dispatch == NO_DISPATCH )
  488.     return;
  489.     PutEof();
  490.     fflush( the_hdr->rle_file );
  491.     /* Free storage allocated by rle_put_init. */
  492.     if ( the_hdr->priv.put.brun != NULL )
  493.     {
  494.     free( the_hdr->priv.put.brun );
  495.     the_hdr->priv.put.brun = NULL;
  496.     }
  497.     /* Signal that puteof has been called. */
  498.     the_hdr->dispatch = NO_DISPATCH;
  499. }
  500.  
  501. #ifndef FASTRUNS
  502. /*****************************************************************
  503.  * TAG( same_color )
  504.  * 
  505.  * Determine if the color at the given index position in the scan rows
  506.  * is the same as the background color.
  507.  * Inputs:
  508.  *     index:        Index to the pixel position in each row.
  509.  *    rows:        array of pointers to the scanlines
  510.  *    bg_color:   the background color
  511.  *    ncolors:    number of color elements/pixel
  512.  * Outputs:
  513.  *     TRUE if the color at row[*][i] is the same as bg_color[*].
  514.  * Assumptions:
  515.  *    [None]
  516.  * Algorithm:
  517.  *    [None]
  518.  */
  519. static int
  520. same_color( index, rows, bg_color, ncolors, bits )
  521. register rle_pixel *rows[];
  522. register int bg_color[];
  523. char *bits;
  524. {
  525.     register int i;
  526.  
  527.     for ( i = 0; i < ncolors; i++, bits++ )
  528.     if ( *bits &&
  529.          rows[i][index] != bg_color[i] )
  530.         return 0;
  531.     return 1;                /* all the same */
  532. }
  533. #endif /* !FASTRUNS */
  534.  
  535. /*****************************************************************
  536.  * TAG( findruns )
  537.  * 
  538.  * Find runs not a given color in the row.
  539.  * Inputs:
  540.  *     row:        Row of pixel values
  541.  *    rowlen:        Number of pixels in the row.
  542.  *    color:        Color to compare against.
  543.  *    nrun:        Number of runs already found (in different colors).
  544.  *    brun:        Runs found in other color channels already.
  545.  * Outputs:
  546.  *     brun:        Modified to reflect merging of runs in this color.
  547.  *    Returns number of runs in brun.
  548.  * Assumptions:
  549.  *
  550.  * Algorithm:
  551.  *     Search for occurences of pixels not of the given color outside the
  552.  *    runs already found.  When some are found, add a new run or extend
  553.  *    an existing one.  Adjacent runs with fewer than two pixels intervening
  554.  *    are merged.
  555.  */
  556. static int findruns( row, rowlen, color, nrun, brun )
  557. register rle_pixel *row;
  558. int rowlen, color, nrun;
  559. short (*brun)[2];
  560. {
  561.     int i = 0, lower, upper;
  562.     register int s, j;
  563.  
  564. #ifdef DEBUG
  565.     fprintf( stderr, "findruns( " );
  566.     for ( s = 0; s < rowlen; s++ )
  567.     fprintf( stderr, "%2x.%s", row[s], (s % 20 == 19) ? "\n\t" : "" );
  568.     if ( s % 20 != 0 )
  569.     fprintf( stderr, "\n\t" );
  570.     fprintf( stderr, "%d, %d, %d, \n\t", rowlen, color, nrun );
  571.     for ( j = 0; j < nrun; j++ )
  572.     fprintf( stderr, "(%3d,%3d) %s", brun[j][0], brun[j][1],
  573.         (j % 6 == 5) ? "\n\t" : "" );
  574.     fprintf( stderr, ")\n" );
  575. #endif
  576.  
  577.     while ( i <= nrun )
  578.     {
  579.     /* Assert: 0 <= i <= rowlen
  580.      * brun[i] is the run following the "blank" space being
  581.      * searched.  If i == rowlen, search after brun[i-1].
  582.      */
  583.  
  584.     /* get lower and upper bounds of search */
  585.  
  586.     if ( i == 0 )
  587.         lower = 0;
  588.     else
  589.         lower = brun[i-1][1] + 1;
  590.  
  591.     if ( i == nrun )
  592.         upper = rowlen - 1;
  593.     else
  594.         upper = brun[i][0] - 1;
  595.  
  596. #ifdef DEBUG
  597.     fprintf( stderr, "Searching before run %d from %d to %d\n",
  598.         i, lower, upper );
  599. #endif
  600.     /* Search for beginning of run != color */
  601. #if  defined(LOCC)&defined(vax)
  602.     s = upper - skpc( (char *)row + lower, upper - lower + 1, color ) + 1;
  603. #else
  604.     for ( s = lower; s <= upper; s++ )
  605.         if ( row[s] != color )
  606.         break;
  607. #endif
  608.  
  609.     if ( s <= upper )    /* found a new run? */
  610.     {
  611.         if ( s > lower + 1 || i == 0 ) /* disjoint from preceding run? */
  612.         {
  613. #ifdef DEBUG
  614.         fprintf( stderr, "Found new run starting at %d\n", s );
  615. #endif
  616.         /* Shift following runs up */
  617.         for ( j = nrun; j > i; j-- )
  618.         {
  619.             brun[j][0] = brun[j-1][0];
  620.             brun[j][1] = brun[j-1][1];
  621.         }
  622.         brun[i][0] = s;
  623.         nrun++;
  624.         }
  625.         else
  626.         {
  627.         i--;        /* just add to preceding run */
  628. #ifdef DEBUG
  629.         fprintf( stderr, "Adding to previous run\n" );
  630. #endif
  631.         }
  632.  
  633. #if defined(LOCC)&defined(vax)
  634.         s = upper - locc( (char *)row + s, upper - s + 1, color ) + 1;
  635. #else
  636.         for ( ; s <= upper; s++ )
  637.         if ( row[s] == color )
  638.             break;
  639. #endif
  640.         brun[i][1] = s - 1;
  641.  
  642. #ifdef DEBUG
  643.         fprintf( stderr, "Ends at %d", s - 1 );
  644. #endif
  645.         if ( s >= upper && i < nrun - 1 ) /* merge with following run */
  646.         {
  647.         brun[i][1] = brun[i+1][1];
  648.         /* move following runs back down */
  649.         for ( j = i + 2; j < nrun; j++ )
  650.         {
  651.             brun[j-1][0] = brun[j][0];
  652.             brun[j-1][1] = brun[j][1];
  653.         }
  654.         nrun--;
  655. #ifdef DEBUG
  656.         fprintf( stderr, ", add to next run" );
  657. #endif
  658.         }
  659. #ifdef DEBUG
  660.         putc( '\n', stderr );
  661. #endif
  662.     }
  663.     
  664.     /* Search in next space */
  665.     i++;
  666.     }
  667.  
  668.     return nrun;
  669. }
  670.  
  671. #ifdef LOCC
  672. /*ARGSUSED*/
  673. int locc( p, l, c )
  674. register char *p;
  675. register int l;
  676. register int c;
  677. {
  678.     asm( "locc    r9,r10,(r11)" );
  679. #ifdef lint
  680.     c = (int) p;        /* why doesn't ARGSUSED work? */
  681.     l = c;
  682.     return l;            /* Needs return value, at least */
  683. #endif
  684. }
  685.  
  686. /*ARGSUSED*/
  687. int skpc( p, l, c )
  688. register char *p;
  689. register int l;
  690. register int c;
  691. {
  692.     asm( "skpc r9,r10,(r11)" );
  693. #ifdef lint
  694.     c = (int) p;        /* why doesn't ARGSUSED work? */
  695.     l = c;
  696.     return l;            /* Needs return value, at least */
  697. #endif
  698. }
  699. #endif
  700. /*
  701.  * This software is copyrighted as noted below.  It may be freely copied,
  702.  * modified, and redistributed, provided that the copyright notice is 
  703.  * preserved on all copies.
  704.  * 
  705.  * There is no warranty or other guarantee of fitness for this software,
  706.  * it is provided solely "as is".  Bug reports or fixes may be sent
  707.  * to the author, who may or may not act on them as he desires.
  708.  *
  709.  * You may not include this software in a program or other software product
  710.  * without supplying the source, or without informing the end-user that the 
  711.  * source is available for no extra charge.
  712.  *
  713.  * If you modify this software, you should include a notice giving the
  714.  * name of the person performing the modification, the date of modification,
  715.  * and the reason for such modification.
  716.  *
  717.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  718.  *  to have all "void" functions so declared.
  719.  */
  720. /* 
  721.  * rle_global.c - Global variable initialization for rle routines.
  722.  * 
  723.  * Author:    Spencer W. Thomas
  724.  *         Computer Science Dept.
  725.  *         University of Utah
  726.  * Date:    Thu Apr 25 1985
  727.  * Copyright (c) 1985,1986 Spencer W. Thomas
  728.  * 
  729.  * $Id: rle_global.c,v 3.0 90/08/03 15:20:54 spencer Exp $
  730.  */
  731.  
  732. extern int    RunSetup( ARB_ARGS ),
  733.         RunSkipBlankLines( ARB_ARGS ),
  734.         RunSetColor( ARB_ARGS ),
  735.         RunSkipPixels( ARB_ARGS ),
  736.         RunNewScanLine( ARB_ARGS ),
  737.         Runputdata( ARB_ARGS ),
  738.         Runputrun( ARB_ARGS ),
  739.         RunputEof( ARB_ARGS );
  740.  
  741. extern void    NullputEof( ARB_ARGS );
  742.  
  743. struct rle_dispatch_tab rle_DTable[] = {
  744.     {
  745.     " OB",
  746.     RunSetup,
  747.     RunSkipBlankLines,
  748.     RunSetColor,
  749.     RunSkipPixels,
  750.     RunNewScanLine,
  751.     Runputdata,
  752.     Runputrun,
  753.     DefaultBlockHook,
  754.     RunputEof
  755.     },
  756. };
  757.  
  758. static int bg_color[3] = { 0, 0, 0 };
  759.  
  760. rle_hdr rle_dflt_hdr = {
  761.     RUN_DISPATCH,        /* dispatch value */
  762.     3,                /* 3 colors */
  763.     bg_color,            /* background color */
  764.     0,                /* (alpha) if 1, save alpha channel */
  765.     2,                /* (background) 0->just save pixels, */
  766.                 /* 1->overlay, 2->clear to bg first */
  767.     0, 511,            /* (xmin, xmax) X bounds to save */
  768.     0, 511,            /* (ymin, ymax) Y bounds to save */
  769.     0,                /* ncmap (if != 0, save color map) */
  770.     8,                /* cmaplen (log2 of length of color map) */
  771.     NULL,            /* pointer to color map */
  772.     NULL,            /* pointer to comment strings */
  773.     stdout,            /* output file */
  774.     { 7 }            /* RGB channels only */
  775.     /* Can't initialize the union */
  776. };
  777. /*
  778.  * This software is copyrighted as noted below.  It may be freely copied,
  779.  * modified, and redistributed, provided that the copyright notice is 
  780.  * preserved on all copies.
  781.  * 
  782.  * There is no warranty or other guarantee of fitness for this software,
  783.  * it is provided solely "as is".  Bug reports or fixes may be sent
  784.  * to the author, who may or may not act on them as he desires.
  785.  *
  786.  * You may not include this software in a program or other software product
  787.  * without supplying the source, or without informing the end-user that the 
  788.  * source is available for no extra charge.
  789.  *
  790.  * If you modify this software, you should include a notice giving the
  791.  * name of the person performing the modification, the date of modification,
  792.  * and the reason for such modification.
  793.  *
  794.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  795.  *  to have all "void" functions so declared.
  796.  */
  797. /* 
  798.  * Runput.c - General purpose Run Length Encoding.
  799.  * 
  800.  * Author:    Spencer W. Thomas
  801.  *         Computer Science Dept.
  802.  *         University of Utah
  803.  * Date:    Mon Aug  9 1982
  804.  * Copyright (c) 1982,1986 Spencer W. Thomas
  805.  * 
  806.  * $Id: Runput.c,v 3.0 90/08/03 15:19:58 spencer Exp $
  807.  * 
  808.  * Modified by:    Todd W. Fuqua
  809.  *     Date:    Jul 22 1984
  810.  * convert to new RLE format to make room for larger frame buffers
  811.  */
  812.  
  813. /* THIS IS WAY OUT OF DATE.  See rle.5.
  814.  * The output file format is:
  815.  * 
  816.  * Word 0:    A "magic" number.  The top byte of the word contains
  817.  *        the letter 'R' or the letter 'W'.  'W' indicates that
  818.  *        only black and white information was saved.  The bottom
  819.  *        byte is one of the following:
  820.  *    ' ':    Means a straight "box" save, -S flag was given.
  821.  *    'B':    Image saved with background color, clear screen to
  822.  *        background before restoring image.
  823.  *    'O':    Image saved in overlay mode.
  824.  * 
  825.  * Words 1-6:    The structure
  826.  * {     short   xpos,            Lower left corner
  827.  *             ypos,
  828.  *             xsize,            Size of saved box
  829.  *             ysize;
  830.  *     char    rgb[3];            Background color
  831.  *     char    map;            flag for map presence
  832.  * }
  833.  * 
  834.  * If the map flag is non-zero, then the color map will follow as 
  835.  * 3*256 16 bit words, first the red map, then the green map, and
  836.  * finally the blue map.
  837.  * 
  838.  * Following the setup information is the Run Length Encoded image.
  839.  * Each instruction consists of a 4-bit opcode, a 12-bit datum and
  840.  * possibly one or more following words (all words are 16 bits).  The
  841.  * instruction opcodes are:
  842.  * 
  843.  * SkipLines (1):   The bottom 10 bits are an unsigned number to be added to
  844.  *            current Y position.
  845.  * 
  846.  * SetColor (2):    The datum indicates which color is to be loaded with
  847.  *             the data described by the following ByteData and
  848.  *             RunData instructions.  0->red, 1->green, 2->blue.  The
  849.  *             operation also resets the X position to the initial
  850.  *             X (i.e. a carriage return operation is performed).
  851.  * 
  852.  * SkipPixels (3):  The bottom 10 bits are an unsigned number to be
  853.  *             added to the current X position.
  854.  * 
  855.  * ByteData (5):    The datum is one less than the number of bytes of
  856.  *             color data following.  If the number of bytes is
  857.  *             odd, a filler byte will be appended to the end of
  858.  *             the byte string to make an integral number of 16-bit
  859.  *             words.  The bytes are in PDP-11 order.  The X
  860.  *             position is incremented to follow the last byte of
  861.  *             data.
  862.  * 
  863.  * RunData (6):        The datum is one less than the run length.  The
  864.  *             following word contains (in its lower 8 bits) the
  865.  *             color of the run.  The X position is incremented to
  866.  *             follow the last byte in the run.
  867.  */
  868.  
  869. #include    "stdio.h"
  870. #include    "rle_code.h"
  871. #ifdef USE_STDLIB_H
  872. #include    <stdlib.h>
  873. #include    <malloc.h>
  874. #else
  875.  
  876. #ifdef USE_STRING_H
  877. #include    <string.h>
  878. #else
  879. #include    <strings.h>
  880. #endif /* USE_STRING_H */
  881.  
  882. #endif /* USE_STDLIB_H */
  883.  
  884. #define UPPER 255            /* anything bigger ain't a byte */
  885.  
  886. /*
  887.  * Macros to make writing instructions with correct byte order easier.
  888.  */
  889. /* Write a two-byte value in little_endian order. */
  890. #define    put16(a)    (putc((a)&0xff,rle_fd),putc(((a)>>8)&0xff,rle_fd))
  891.  
  892. /* short instructions */
  893. #define mk_short_1(oper,a1)        /* one argument short */ \
  894.     putc(oper,rle_fd), putc((char)a1,rle_fd)
  895.  
  896. #define mk_short_2(oper,a1,a2)        /* two argument short */ \
  897.     putc(oper,rle_fd), putc((char)a1,rle_fd), put16(a2)
  898.  
  899. /* long instructions */
  900. #define mk_long_1(oper,a1)        /* one argument long */ \
  901.     putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), put16(a1)
  902.  
  903. #define mk_long_2(oper,a1,a2)        /* two argument long */ \
  904.     putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), \
  905.     put16(a1), put16(a2)
  906.  
  907. /* choose between long and short format instructions */
  908. /* NOTE: these macros can only be used where a STATEMENT is legal */
  909.  
  910. #define mk_inst_1(oper,a1)        /* one argument inst */ \
  911.     if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1))
  912.  
  913. #define mk_inst_2(oper,a1,a2)        /* two argument inst */ \
  914.     if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2))
  915.  
  916. /* 
  917.  * Opcode definitions
  918.  */
  919. #define        RSkipLines(n)           mk_inst_1(RSkipLinesOp,(n))
  920.  
  921. #define        RSetColor(c)        mk_short_1(RSetColorOp,(c))
  922.                     /* has side effect of performing */
  923.                     /* "carriage return" action */
  924.  
  925. #define        RSkipPixels(n)        mk_inst_1(RSkipPixelsOp,(n))
  926.  
  927. #define        RNewLine            RSkipLines(1)
  928.  
  929. #define        RByteData(n)        mk_inst_1(RByteDataOp,n)
  930.                     /* followed by ((n+1)/2)*2 bytes */
  931.                     /* of data.  If n is odd, last */
  932.                     /* byte will be ignored */
  933.                     /* "cursor" is left at pixel */
  934.                     /* following last pixel written */
  935.  
  936. #define        RRunData(n,c)        mk_inst_2(RRunDataOp,(n),(c))
  937.                     /* next word contains color data */
  938.                     /* "cursor" is left at pixel after */
  939.                     /* end of run */
  940.  
  941. #define     REOF            mk_inst_1(REOFOp,0)
  942.                     /* Really opcode only */
  943.  
  944. extern char *vax_pshort();
  945.  
  946. /*****************************************************************
  947.  * TAG( RunSetup )
  948.  * Put out initial setup data for RLE files.
  949.  */
  950. int RunSetup(the_hdr)
  951. register rle_hdr * the_hdr;
  952. {
  953.     struct XtndRsetup setup;
  954.     register FILE * rle_fd = the_hdr->rle_file;
  955.  
  956.     put16( RLE_MAGIC );
  957.  
  958.     if ( the_hdr->background == 2 )
  959.     setup.h_flags = H_CLEARFIRST;
  960.     else if ( the_hdr->background == 0 )
  961.     setup.h_flags = H_NO_BACKGROUND;
  962.     else
  963.     setup.h_flags = 0;
  964.     if ( the_hdr->alpha )
  965.     setup.h_flags |= H_ALPHA;
  966.     if ( the_hdr->comments != NULL && *the_hdr->comments != NULL )
  967.     setup.h_flags |= H_COMMENT;
  968.  
  969.     setup.h_ncolors = the_hdr->ncolors;
  970.     setup.h_pixelbits = 8;        /* Grinnell dependent */
  971.     if ( the_hdr->ncmap > 0 && the_hdr->cmap == NULL )
  972.     {
  973.     fprintf( stderr,
  974.          "Color map of size %d*%d specified, but not supplied\n" );
  975.     the_hdr->ncmap = 0;
  976.     }
  977.     setup.h_cmaplen = the_hdr->cmaplen;    /* log2 of color map size */
  978.     setup.h_ncmap = the_hdr->ncmap;    /* no of color channels */
  979.     vax_pshort(setup.hc_xpos,the_hdr->xmin);
  980.     vax_pshort(setup.hc_ypos,the_hdr->ymin);
  981.     vax_pshort(setup.hc_xlen,the_hdr->xmax - the_hdr->xmin + 1);
  982.     vax_pshort(setup.hc_ylen,the_hdr->ymax - the_hdr->ymin + 1);
  983.     fwrite((char *)&setup, SETUPSIZE, 1, rle_fd);
  984.     if ( the_hdr->background != 0 )
  985.     {
  986.     register int i;
  987.     register rle_pixel *background =
  988.         (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) );
  989.     register int *bg_color;
  990.     /* 
  991.      * If even number of bg color bytes, put out one more to get to 
  992.      * 16 bit boundary.
  993.      */
  994.     bg_color = the_hdr->bg_color;
  995.     for ( i = 0; i < the_hdr->ncolors; i++ )
  996.         background[i] =  *bg_color++;
  997.     /* Extra byte, if written, should be 0. */
  998.     background[i] = 0;
  999.     fwrite((char *)background, (the_hdr->ncolors / 2) * 2 + 1, 1, rle_fd);
  1000.     free( background );
  1001.     }
  1002.     else
  1003.     putc( '\0', rle_fd );
  1004.     if (the_hdr->ncmap > 0)
  1005.     {
  1006.     /* Big-endian machines are harder */
  1007.     register int i, nmap = (1 << the_hdr->cmaplen) *
  1008.                    the_hdr->ncmap;
  1009.     register char *h_cmap = (char *)malloc( nmap * 2 );
  1010.     if ( h_cmap == NULL )
  1011.     {
  1012.         fprintf( stderr, "Malloc failed for color map of size %d\n",
  1013.              nmap );
  1014.         exit( 1 );
  1015.     }
  1016.     for ( i = 0; i < nmap; i++ )
  1017.         vax_pshort( &h_cmap[i*2], the_hdr->cmap[i] );
  1018.  
  1019.     fwrite( h_cmap, nmap, 2, rle_fd );
  1020.     free( h_cmap );
  1021.     }
  1022.  
  1023.     /* Now write out comments if given */
  1024.     if ( setup.h_flags & H_COMMENT )
  1025.     {
  1026.     int comlen;
  1027.     register CONST_DECL char ** com_p;
  1028.  
  1029.     /* Get the total length of comments */
  1030.     comlen = 0;
  1031.     for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
  1032.         comlen += 1 + strlen( *com_p );
  1033.  
  1034.     put16( comlen );
  1035.     for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
  1036.         fwrite( *com_p, 1, strlen( *com_p ) + 1, rle_fd );
  1037.  
  1038.     if ( comlen & 1 )    /* if odd length, round up */
  1039.         putc( '\0', rle_fd );
  1040.     }
  1041. }
  1042.  
  1043. /*****************************************************************
  1044.  * TAG( RunSkipBlankLines )
  1045.  * Skip one or more blank lines in the RLE file.
  1046.  */
  1047. int RunSkipBlankLines(nblank, the_hdr)
  1048. int nblank;
  1049. register rle_hdr * the_hdr;
  1050. {
  1051.     register FILE * rle_fd = the_hdr->rle_file;
  1052.     RSkipLines(nblank);
  1053. }
  1054.  
  1055. /*****************************************************************
  1056.  * TAG( RunSetColor )
  1057.  * Select a color and do carriage return.
  1058.  * color: 0 = Red, 1 = Green, 2 = Blue.
  1059.  */
  1060. int RunSetColor(c, the_hdr)
  1061. int c;
  1062. register rle_hdr * the_hdr;
  1063. {
  1064.     register FILE * rle_fd = the_hdr->rle_file;
  1065.     RSetColor(c);
  1066. }
  1067.  
  1068. /*****************************************************************
  1069.  * TAG( RunSkipPixels )
  1070.  * Skip a run of background.
  1071.  */
  1072.  
  1073. /* ARGSUSED */
  1074. int RunSkipPixels(nskip, last, wasrun, the_hdr)
  1075. int nskip, last, wasrun;
  1076. register rle_hdr * the_hdr;
  1077. {
  1078.     register FILE * rle_fd = the_hdr->rle_file;
  1079.     if (! last && nskip > 0)
  1080.     {
  1081.     RSkipPixels(nskip);
  1082.     }
  1083. }
  1084.  
  1085. /*****************************************************************
  1086.  * TAG( RunNewScanLine )
  1087.  * Perform a newline action.  Since CR is implied by the Set Color
  1088.  * operation, only generate code if the newline flag is true.
  1089.  */
  1090. int RunNewScanLine (int flag, register rle_hdr *the_hdr)
  1091. /*
  1092. int RunNewScanLine(flag, the_hdr)
  1093. int flag;
  1094. register rle_hdr * the_hdr;
  1095. */
  1096. {
  1097.     register FILE * rle_fd = the_hdr->rle_file;
  1098.     if (flag)
  1099.     {
  1100.     RNewLine;
  1101.     }
  1102. }
  1103.  
  1104. /*****************************************************************
  1105.  * TAG( Runputdata )
  1106.  * Put one or more pixels of byte data into the output file.
  1107.  */
  1108. int Runputdata(buf, n, the_hdr)
  1109. rle_pixel * buf;
  1110. int n;
  1111. register rle_hdr * the_hdr;
  1112. {
  1113.     register FILE * rle_fd = the_hdr->rle_file;
  1114.     if (n == 0)
  1115.     return;
  1116.  
  1117.     RByteData(n-1);
  1118.     fwrite((char *)buf, n, 1, rle_fd);
  1119.     if ( n & 1 )
  1120.     putc( 0, rle_fd );
  1121. }
  1122.  
  1123. /*****************************************************************
  1124.  * TAG( Runputrun )
  1125.  * Output a single color run.
  1126.  */
  1127.  
  1128. /* ARGSUSED */
  1129. int Runputrun(color, n, last, the_hdr)
  1130. int color, n, last;
  1131. register rle_hdr * the_hdr;
  1132. {
  1133.     register FILE * rle_fd = the_hdr->rle_file;
  1134.     RRunData(n-1,color);
  1135. }
  1136.  
  1137.  
  1138. /*****************************************************************
  1139.  * TAG( RunputEof )
  1140.  * Output an EOF opcode
  1141.  */
  1142. int RunputEof( the_hdr )
  1143. register rle_hdr * the_hdr;
  1144. {
  1145.     register FILE * rle_fd = the_hdr->rle_file;
  1146.     REOF;
  1147. }
  1148. /*
  1149.  *            V A X S H O R T
  1150.  *
  1151.  *  Code to manipulate 16-bit integers in VAX order in a
  1152.  *  machine independent manner.
  1153.  *
  1154.  *  (VAX is a trademark of Digital Equipment Corporation)
  1155.  *
  1156.  *  Author -
  1157.  *    Michael John Muuss
  1158.  *  
  1159.  *  Source -
  1160.  *    SECAD/VLD Computing Consortium, Bldg 394
  1161.  *    The U. S. Army Ballistic Research Laboratory
  1162.  *    Aberdeen Proving Ground, Maryland  21005-5066
  1163.  *  
  1164.  *  Distribution Status -
  1165.  *    Public Domain, Distribution Unlimitied.
  1166.  */
  1167. #ifndef lint
  1168. static char RCSid[] = "@(#)$Id: vaxshort.c,v 3.0 90/08/03 15:21:30 spencer Exp $ (BRL)";
  1169. #endif
  1170.  
  1171. /*
  1172.  *            V A X _ P S H O R T
  1173.  */
  1174. char *vax_pshort(msgp, s)
  1175. register char *msgp;
  1176. register unsigned short s;
  1177. {
  1178.  
  1179.     msgp[0] = s & 0xFF;
  1180.     msgp[1] = s >> 8;
  1181.     return(msgp+2);
  1182. }
  1183.