home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / rlelib.c < prev    next >
C/C++ Source or Header  |  1993-10-21  |  48KB  |  1,708 lines

  1. /*
  2.  *    Utah RLE Toolkit library routines.
  3.  * 
  4.  *     Read image support only.
  5.  * 
  6.  *     Cobbled from Utah RLE include and library source files.
  7.  * 
  8.  *     By Graeme Gill
  9.  *     30/5/90
  10.  *
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include <varargs.h>
  16. #include <ctype.h>
  17.  
  18. #include "image.h"        /* need ZFILE definition */
  19. #include "rle.h"
  20.  
  21. /* SUPPRESS 530 */
  22. /* SUPPRESS 558 */
  23. /* SUPPRESS 590 */
  24.  
  25. #define zeof(zfp) feof((zfp)->stream)
  26. #define zclearerr(zfp) clearerr((zfp)->stream)
  27.  
  28. /*
  29.  * This software is copyrighted as noted below.  It may be freely copied,
  30.  * modified, and redistributed, provided that the copyright notice is 
  31.  * preserved on all copies.
  32.  * 
  33.  * There is no warranty or other guarantee of fitness for this software,
  34.  * it is provided solely "as is".  Bug reports or fixes may be sent
  35.  * to the author, who may or may not act on them as he desires.
  36.  *
  37.  * You may not include this software in a program or other software product
  38.  * without supplying the source, or without informing the end-user that the 
  39.  * source is available for no extra charge.
  40.  *
  41.  * If you modify this software, you should include a notice giving the
  42.  * name of the person performing the modification, the date of modification,
  43.  * and the reason for such modification.
  44.  */
  45. /* 
  46.  * Runsv.h - Definitions for Run Length Encoding.
  47.  * 
  48.  * Author:    Spencer W. Thomas
  49.  *         Computer Science Dept.
  50.  *         University of Utah
  51.  * Date:    Mon Aug  9 1982
  52.  * Copyright (c) 1982 Spencer W. Thomas
  53.  */
  54.  
  55. #ifndef XTNDRUNSV
  56. #define XTNDRUNSV
  57.  
  58. /* 
  59.  * Opcode definitions
  60.  */
  61.  
  62. #define     LONG                0x40
  63. #define        RSkipLinesOp    1
  64. #define        RSetColorOp        2
  65. #define        RSkipPixelsOp    3
  66. #define        RByteDataOp        5
  67. #define        RRunDataOp        6
  68. #define        REOFOp        7
  69.  
  70. #define     H_CLEARFIRST        0x1    /* clear framebuffer flag */
  71. #define        H_NO_BACKGROUND    0x2    /* if set, no bg color supplied */
  72. #define        H_ALPHA        0x4   /* if set, alpha channel (-1) present */
  73. #define        H_COMMENT        0x8    /* if set, comments present */
  74.  
  75. struct XtndRsetup
  76. {
  77.     short   h_xpos,
  78.             h_ypos,
  79.             h_xlen,
  80.             h_ylen;
  81.     char    h_flags,
  82.             h_ncolors,
  83.         h_pixelbits,
  84.         h_ncmap,
  85.         h_cmaplen;
  86. };
  87. #define        SETUPSIZE    ((4*2)+5)
  88.  
  89. /* "Old" RLE format magic numbers */
  90. #define        RMAGIC    ('R' << 8)    /* top half of magic number */
  91. #define        WMAGIC    ('W' << 8)    /* black&white rle image */
  92.  
  93. #define        XtndRMAGIC    ((short)0xcc52)    /* RLE file magic number */
  94.  
  95. #endif /* XTNDRUNSV */
  96.  
  97. /*  "svfb.h" */
  98. /*
  99.  * This software is copyrighted as noted below.  It may be freely copied,
  100.  * modified, and redistributed, provided that the copyright notice is 
  101.  * preserved on all copies.
  102.  * 
  103.  * There is no warranty or other guarantee of fitness for this software,
  104.  * it is provided solely "as is".  Bug reports or fixes may be sent
  105.  * to the author, who may or may not act on them as he desires.
  106.  *
  107.  * You may not include this software in a program or other software product
  108.  * without supplying the source, or without informing the end-user that the 
  109.  * source is available for no extra charge.
  110.  *
  111.  * If you modify this software, you should include a notice giving the
  112.  * name of the person performing the modification, the date of modification,
  113.  * and the reason for such modification.
  114.  */
  115. /* 
  116.  * svfb.h - Definitions and a few global variables for svfb.
  117.  * 
  118.  * Author:    Spencer W. Thomas
  119.  *         Computer Science Dept.
  120.  *         University of Utah
  121.  * Date:    Mon Aug  9 1982
  122.  * Copyright (c) 1982 Spencer W. Thomas
  123.  */
  124.  
  125. /* ****************************************************************
  126.  * Dispatch table for different output types.
  127.  */
  128. typedef void sv_fn();
  129. struct sv_dispatch_tab {
  130.     char   *magic;            /* magic type flags */
  131.     sv_fn  *setup,            /* startup function */
  132.        *skipBlankLines,
  133.        *setColor,
  134.        *skipPixels,
  135.        *newScanLine,
  136.        *putdat,            /* put a set of differing pixels */
  137.        *putrn,            /* put a run all the same */
  138.        *blockHook,            /* hook called at start of new */
  139.                     /* output block */
  140.        *putEof;        /* write EOF marker (if possible) */
  141. };
  142.  
  143. /* 
  144.  * These definitions presume the existence of a variable called
  145.  * "fileptr", declared "long * fileptr".  *fileptr should be
  146.  * initialized to 0 before calling Setup().
  147.  * A pointer "globals" declared "struct sv_globals * globals" is also
  148.  * presumed to exist.
  149.  */
  150. #define        sv_magic        (sv_DTable[(int)globals->sv_dispatch].magic)
  151. #define        Setup()        (*sv_DTable[(int)globals->sv_dispatch].setup)(globals)
  152. #define        SkipBlankLines(n)    (*sv_DTable[(int)globals->sv_dispatch].skipBlankLines)(n, globals)
  153. #define        SetColor(c)        (*sv_DTable[(int)globals->sv_dispatch].setColor)(c, globals)
  154. #define        SkipPixels(n, l, r)    (*sv_DTable[(int)globals->sv_dispatch].skipPixels)(n,l,r, globals)
  155. #define        NewScanLine(flag)    (*sv_DTable[(int)globals->sv_dispatch].newScanLine)(flag, globals)
  156. #define        putdata(buf, len)    (*sv_DTable[(int)globals->sv_dispatch].putdat)(buf, len, globals)
  157. #define        putrun(val, len, f)    (*sv_DTable[(int)globals->sv_dispatch].putrn)(val,len,f, globals)
  158. #define        BlockHook()        (*sv_DTable[(int)globals->sv_dispatch].blockHook)(globals)
  159. #define        PutEof()        (*sv_DTable[(int)globals->sv_dispatch].putEof)(globals)
  160.  
  161. /* 
  162.  * States for run detection
  163.  */
  164. #define    DATA    0
  165. #define    RUN2    1
  166. #define RUN3    2
  167. #define    RUN4    3
  168. #define    INRUN    -1
  169.  
  170. /*
  171.  * This software is copyrighted as noted below.  It may be freely copied,
  172.  * modified, and redistributed, provided that the copyright notice is 
  173.  * preserved on all copies.
  174.  * 
  175.  * There is no warranty or other guarantee of fitness for this software,
  176.  * it is provided solely "as is".  Bug reports or fixes may be sent
  177.  * to the author, who may or may not act on them as he desires.
  178.  *
  179.  * You may not include this software in a program or other software product
  180.  * without supplying the source, or without informing the end-user that the 
  181.  * source is available for no extra charge.
  182.  *
  183.  * If you modify this software, you should include a notice giving the
  184.  * name of the person performing the modification, the date of modification,
  185.  * and the reason for such modification.
  186.  *
  187.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  188.  *  to have all "void" functions so declared.
  189.  */
  190. /* 
  191.  * svfb_global.c - Global variable initialization for svfb routines.
  192.  * 
  193.  * Author:    Spencer W. Thomas
  194.  *         Computer Science Dept.
  195.  *         University of Utah
  196.  * Date:    Thu Apr 25 1985
  197.  * Copyright (c) 1985,1986 Spencer W. Thomas
  198.  */
  199.  
  200.  
  201. void    RunSetup(),
  202.         RunSkipBlankLines(),
  203.         RunSetColor(),
  204.         RunSkipPixels(),
  205.         RunNewScanLine(),
  206.         Runputdata(),
  207.         Runputrun(),
  208.         RunputEof();
  209.  
  210. void    DefaultBlockHook();
  211. void    NullputEof();
  212.  
  213. struct sv_dispatch_tab sv_DTable[10] = {
  214.     {
  215.     " OB",
  216.     RunSetup,
  217.     RunSkipBlankLines,
  218.     RunSetColor,
  219.     RunSkipPixels,
  220.     RunNewScanLine,
  221.     Runputdata,
  222.     Runputrun,
  223.     DefaultBlockHook,
  224.     RunputEof
  225.     },
  226. };
  227.  
  228. static int sv_bg_color[3] = { 0, 0, 0 };
  229.  
  230. struct sv_globals sv_globals = {
  231.     RUN_DISPATCH,        /* dispatch value */
  232.     3,                /* 3 colors */
  233.     sv_bg_color,        /* background color */
  234.     0,                /* (alpha) if 1, save alpha channel */
  235.     2,                /* (background) 0->just save pixels, */
  236.                 /* 1->overlay, 2->clear to bg first */
  237.     0, 511,            /* (xmin, xmax) X bounds to save */
  238.     0, 479,            /* (ymin, ymax) Y bounds to save */
  239.     0,                /* ncmap (if != 0, save color map) */
  240.     8,                /* cmaplen (log2 of length of color map) */
  241.     NULL,            /* pointer to color map */
  242.     NULL,            /* pointer to comment strings */
  243.     NULL,            /* output file */
  244.     { 7 }            /* RGB channels only */
  245.     /* Can't initialize the union */
  246. };
  247.  
  248. /* ARGSUSED */
  249. void
  250. NullputEof(globals)
  251. struct sv_globals * globals;
  252. {
  253.                 /* do nothing */
  254. }
  255.  
  256. /*
  257.  * This software is copyrighted as noted below.  It may be freely copied,
  258.  * modified, and redistributed, provided that the copyright notice is 
  259.  * preserved on all copies.
  260.  * 
  261.  * There is no warranty or other guarantee of fitness for this software,
  262.  * it is provided solely "as is".  Bug reports or fixes may be sent
  263.  * to the author, who may or may not act on them as he desires.
  264.  *
  265.  * You may not include this software in a program or other software product
  266.  * without supplying the source, or without informing the end-user that the 
  267.  * source is available for no extra charge.
  268.  *
  269.  * If you modify this software, you should include a notice giving the
  270.  * name of the person performing the modification, the date of modification,
  271.  * and the reason for such modification.
  272.  *
  273.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  274.  *  to have all "void" functions so declared.
  275.  */
  276. /* 
  277.  * Runsv.c - General purpose Run Length Encoding for svfb.
  278.  * 
  279.  * Author:    Spencer W. Thomas
  280.  *         Computer Science Dept.
  281.  *         University of Utah
  282.  * Date:    Mon Aug  9 1982
  283.  * Copyright (c) 1982,1986 Spencer W. Thomas
  284.  */
  285.  
  286. /* THIS IS WAY OUT OF DATE.  See rle.5.
  287.  * The output file format is:
  288.  * 
  289.  * Word 0:    A "magic" number.  The top byte of the word contains
  290.  *        the letter 'R' or the letter 'W'.  'W' indicates that
  291.  *        only black and white information was saved.  The bottom
  292.  *        byte is one of the following:
  293.  *    ' ':    Means a straight "box" save, -S flag was given.
  294.  *    'B':    Image saved with background color, clear screen to
  295.  *        background before restoring image.
  296.  *    'O':    Image saved in overlay mode.
  297.  * 
  298.  * Words 1-6:    The structure
  299.  * {   short   xpos,            * Lower left corner
  300.  *             ypos,
  301.  *             xsize,            * Size of saved box
  302.  *             ysize;
  303.  *     char    rgb[3];            * Background color
  304.  *     char    map;            * flag for map presence
  305.  * }
  306.  * 
  307.  * If the map flag is non-zero, then the color map will follow as 
  308.  * 3*256 16 bit words, first the red map, then the green map, and
  309.  * finally the blue map.
  310.  * 
  311.  * Following the setup information is the Run Length Encoded image.
  312.  * Each instruction consists of a 4-bit opcode, a 12-bit datum and
  313.  * possibly one or more following words (all words are 16 bits).  The
  314.  * instruction opcodes are:
  315.  * 
  316.  * SkipLines (1):   The bottom 10 bits are an unsigned number to be added to
  317.  *            current Y position.
  318.  * 
  319.  * SetColor (2):    The datum indicates which color is to be loaded with
  320.  *             the data described by the following ByteData and
  321.  *             RunData instructions.  0->red, 1->green, 2->blue.  The
  322.  *             operation also resets the X position to the initial
  323.  *             X (i.e. a carriage return operation is performed).
  324.  * 
  325.  * SkipPixels (3):  The bottom 10 bits are an unsigned number to be
  326.  *             added to the current X position.
  327.  * 
  328.  * ByteData (5):    The datum is one less than the number of bytes of
  329.  *             color data following.  If the number of bytes is
  330.  *             odd, a filler byte will be appended to the end of
  331.  *             the byte string to make an integral number of 16-bit
  332.  *             words.  The bytes are in PDP-11 order.  The X
  333.  *             position is incremented to follow the last byte of
  334.  *             data.
  335.  * 
  336.  * RunData (6):        The datum is one less than the run length.  The
  337.  *             following word contains (in its lower 8 bits) the
  338.  *             color of the run.  The X position is incremented to
  339.  *             follow the last byte in the run.
  340.  */
  341.  
  342. #define UPPER 255            /* anything bigger ain't a byte */
  343.  
  344. /* Predefine LITTLE_ENDIAN for vax and pdp11 machines */
  345. #if defined(vax) || defined(pdp11)
  346. #define LITTLE_ENDIAN
  347. #endif
  348.  
  349. /*
  350.  * Macros to make writing instructions with correct byte order easier.
  351.  */
  352. union { short s; char c[2]; } arg;
  353. #ifdef LITTLE_ENDIAN
  354. #define    put16(a)    arg.s=a,putc(arg.c[0],sv_fd), putc(arg.c[1],sv_fd)
  355. #else
  356. #define    put16(a)    arg.s=a,putc(arg.c[1],sv_fd), putc(arg.c[0],sv_fd)
  357. #endif
  358.  
  359. /* short instructions */
  360. #define mk_short_1(oper,a1)        /* one argument short */ \
  361.     putc(oper,sv_fd), putc((char)a1,sv_fd)
  362.  
  363. #define mk_short_2(oper,a1,a2)        /* two argument short */ \
  364.     putc(oper,sv_fd), putc((char)a1,sv_fd), put16(a2)
  365.  
  366. /* long instructions */
  367. #define mk_long_1(oper,a1)        /* one argument long */ \
  368.     putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), put16(a1)
  369.  
  370. #define mk_long_2(oper,a1,a2)        /* two argument long */ \
  371.     putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), \
  372.     put16(a1), put16(a2)
  373.  
  374. /* choose between long and short format instructions */
  375. /* NOTE: these macros can only be used where a STATEMENT is legal */
  376.  
  377. #define mk_inst_1(oper,a1)        /* one argument inst */ \
  378.     if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1))
  379.  
  380. #define mk_inst_2(oper,a1,a2)        /* two argument inst */ \
  381.     if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2))
  382.  
  383. /* 
  384.  * Opcode definitions
  385.  */
  386. #define        RSkipLines(n)           mk_inst_1(RSkipLinesOp,(n))
  387.  
  388. #define        RSetColor(c)        mk_short_1(RSetColorOp,(c))
  389.                     /* has side effect of performing */
  390.                     /* "carriage return" action */
  391.  
  392. #define        RSkipPixels(n)        mk_inst_1(RSkipPixelsOp,(n))
  393.  
  394. #define        RNewLine            RSkipLines(1)
  395.  
  396. #define        RByteData(n)        mk_inst_1(RByteDataOp,n)
  397.                     /* followed by ((n+1)/2)*2 bytes */
  398.                     /* of data.  If n is odd, last */
  399.                     /* byte will be ignored */
  400.                     /* "cursor" is left at pixel */
  401.                     /* following last pixel written */
  402.  
  403. #define        RRunData(n,c)        mk_inst_2(RRunDataOp,(n),(c))
  404.                     /* next word contains color data */
  405.                     /* "cursor" is left at pixel after */
  406.                     /* end of run */
  407.  
  408. #define     REOF            mk_inst_1(REOFOp,0)
  409.                     /* Really opcode only */
  410.  
  411. /*****************************************************************
  412.  * TAG( RunSetup )
  413.  * Put out initial setup data for RLE svfb files.
  414.  */
  415. void
  416. RunSetup(globals)
  417. register struct sv_globals * globals;
  418. {
  419. }
  420.  
  421. /*****************************************************************
  422.  * TAG( RunSkipBlankLines )
  423.  * Skip one or more blank lines in the RLE file.
  424.  */
  425. void
  426. RunSkipBlankLines(nblank, globals)
  427. register struct sv_globals * globals;
  428. {
  429. }
  430.  
  431. /*****************************************************************
  432.  * TAG( RunSetColor )
  433.  * Select a color and do carriage return.
  434.  * color: 0 = Red, 1 = Green, 2 = Blue.
  435.  */
  436. void
  437. RunSetColor(c, globals)
  438. register struct sv_globals * globals;
  439. {
  440. }
  441.  
  442. /*****************************************************************
  443.  * TAG( RunSkipPixels )
  444.  * Skip a run of background.
  445.  */
  446.  
  447. /* ARGSUSED */
  448. void
  449. RunSkipPixels(nskip, last, wasrun, globals)
  450. register struct sv_globals * globals;
  451. {
  452. }
  453.  
  454. /*****************************************************************
  455.  * TAG( RunNewScanLine )
  456.  * Perform a newline action.  Since CR is implied by the Set Color
  457.  * operation, only generate code if the newline flag is true.
  458.  */
  459. void
  460. RunNewScanLine(flag, globals)
  461. register struct sv_globals * globals;
  462. {
  463. }
  464.  
  465. /*****************************************************************
  466.  * TAG( Runputdata )
  467.  * Put one or more pixels of byte data into the output file.
  468.  */
  469. void
  470. Runputdata(buf, n, globals)
  471. rle_pixel * buf;
  472. register struct sv_globals * globals;
  473. {
  474. }
  475.  
  476. /*****************************************************************
  477.  * TAG( Runputrun )
  478.  * Output a single color run.
  479.  */
  480.  
  481. /* ARGSUSED */
  482. void
  483. Runputrun(color, n, last, globals)
  484. register struct sv_globals * globals;
  485. {
  486. }
  487.  
  488.  
  489. /*****************************************************************
  490.  * TAG( RunputEof )
  491.  * Output an EOF opcode
  492.  */
  493. void
  494. RunputEof( globals )
  495. register struct sv_globals * globals;
  496. {
  497. }
  498.  
  499. /*ARGSUSED*/
  500. void
  501. DefaultBlockHook(globals)
  502. struct sv_globals * globals;
  503. {
  504. }
  505.  
  506.  
  507. /*
  508.  * This software is copyrighted as noted below.  It may be freely copied,
  509.  * modified, and redistributed, provided that the copyright notice is 
  510.  * preserved on all copies.
  511.  * 
  512.  * There is no warranty or other guarantee of fitness for this software,
  513.  * it is provided solely "as is".  Bug reports or fixes may be sent
  514.  * to the author, who may or may not act on them as he desires.
  515.  *
  516.  * You may not include this software in a program or other software product
  517.  * without supplying the source, or without informing the end-user that the 
  518.  * source is available for no extra charge.
  519.  *
  520.  * If you modify this software, you should include a notice giving the
  521.  * name of the person performing the modification, the date of modification,
  522.  * and the reason for such modification.
  523.  */
  524. /* 
  525.  * buildmap.c - Build a color map from the RLE file color map.
  526.  * 
  527.  * Author:    Spencer W. Thomas
  528.  *         Computer Science Dept.
  529.  *         University of Utah
  530.  * Date:    Sat Jan 24 1987
  531.  * Copyright (c) 1987, University of Utah
  532.  */
  533.  
  534. /*****************************************************************
  535.  * TAG( buildmap )
  536.  * 
  537.  * Returns a color map that can easily be used to map the pixel values in
  538.  * an RLE file.  Map is built from the color map in the input file.
  539.  * Inputs:
  540.  *     globals:    sv_globals structure containing color map.
  541.  *    minmap:        Minimum number of channels in output map.
  542.  *    gamma:        Adjust color map for this image gamma value
  543.  *            (1.0 means no adjustment).
  544.  * Outputs:
  545.  *     Returns an array of pointers to arrays of rle_pixels.  The array
  546.  *    of pointers contains max(sv_ncolors, sv_ncmap) elements, each 
  547.  *    array of pixels contains 2^sv_cmaplen elements.  The pixel arrays
  548.  *    should be considered read-only.
  549.  * Assumptions:
  550.  *     [None]
  551.  * Algorithm:
  552.  *    Ensure that there are at least sv_ncolors rows in the map, and
  553.  *    that each has at least 256 elements in it (largest map that can
  554.  *    be addressed by an rle_pixel).
  555.  */
  556. rle_pixel **
  557. buildmap( globals, minmap, gamma )
  558. struct sv_globals *globals;
  559. int minmap;
  560. double gamma;
  561. {
  562.     rle_pixel ** cmap, * gammap;
  563.     register int i, j;
  564.     int maplen, cmaplen, ncmap, nmap;
  565.  
  566.     if ( globals->sv_ncmap == 0 )    /* make identity map */
  567.     {
  568.     nmap = (minmap < globals->sv_ncolors) ? globals->sv_ncolors : minmap;
  569.     cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  570.     cmap[0] = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) );
  571.     for ( i = 0; i < 256; i++ )
  572.         cmap[0][i] = i;
  573.     for ( i = 1; i < nmap; i++ )
  574.         cmap[i] = cmap[0];
  575.     maplen = 256;
  576.     ncmap = 1;        /* number of unique rows */
  577.     }
  578.     else            /* make map from globals */
  579.     {
  580.     /* Map is at least 256 long */
  581.     cmaplen = (1 << globals->sv_cmaplen);
  582.     if ( cmaplen < 256 )
  583.         maplen = 256;
  584.     else
  585.         maplen = cmaplen;
  586.  
  587.     if ( globals->sv_ncmap == 1 )    /* make "b&w" map */
  588.     {
  589.         nmap = (minmap < globals->sv_ncolors) ?
  590.         globals->sv_ncolors : minmap;
  591.         cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  592.         cmap[0] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) );
  593.         for ( i = 0; i < maplen; i++ )
  594.         if ( i < cmaplen )
  595.             cmap[0][i] = globals->sv_cmap[i] >> 8;
  596.         else
  597.             cmap[0][i] = i;
  598.         for ( i = 1; i < nmap; i++ )
  599.         cmap[i] = cmap[0];
  600.         ncmap = 1;
  601.     }
  602.     else if ( globals->sv_ncolors <= globals->sv_ncmap )
  603.     {
  604.         nmap = (minmap < globals->sv_ncmap) ? globals->sv_ncmap : minmap;
  605.         cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  606.         for ( j = 0; j < globals->sv_ncmap; j++ )
  607.         {
  608.         cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) );
  609.         for ( i = 0; i < maplen; i++ )
  610.             if ( i < cmaplen )
  611.             cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8;
  612.             else
  613.             cmap[j][i] = i;
  614.         }
  615.         for ( i = j, j--; i < nmap; i++ )
  616.         cmap[i] = cmap[j];
  617.         ncmap = globals->sv_ncmap;
  618.     }
  619.     else            /* ncolors > ncmap */
  620.     {
  621.         nmap = (minmap < globals->sv_ncolors) ?
  622.         globals->sv_ncolors : minmap;
  623.         cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) );
  624.         for ( j = 0; j < globals->sv_ncmap; j++ )
  625.         {
  626.         cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) );
  627.         for ( i = 0; i < maplen; i++ )
  628.             if ( i < cmaplen )
  629.             cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8;
  630.             else
  631.             cmap[j][i] = i;
  632.         }
  633.         for( i = j, j--; i < nmap; i++ )
  634.         cmap[i] = cmap[j];
  635.         ncmap = globals->sv_ncmap;
  636.     }
  637.     }
  638.         
  639.     /* Gamma compensate if requested */
  640.     if ( gamma != 1.0 )
  641.     {
  642.     gammap = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) );
  643.     for ( i = 0; i < 256; i++ )
  644.         {
  645. #ifdef BYTEBUG
  646.         int byteb1;
  647.         byteb1 = (int)(0.5 + 255.0 * pow( i / 255.0, gamma ));
  648.         gammap[i] = byteb1;
  649. #else
  650.         gammap[i] = (int)(0.5 + 255.0 * pow( i / 255.0, gamma ));
  651. #endif
  652.         }
  653.     for ( i = 0; i < ncmap; i++ )
  654.         for ( j = 0; j < maplen; j++ )
  655.         cmap[i][j] = gammap[cmap[i][j]];
  656.     }
  657.  
  658.     return cmap;
  659. }
  660.  
  661. /*
  662.  * This software is copyrighted as noted below.  It may be freely copied,
  663.  * modified, and redistributed, provided that the copyright notice is 
  664.  * preserved on all copies.
  665.  * 
  666.  * There is no warranty or other guarantee of fitness for this software,
  667.  * it is provided solely "as is".  Bug reports or fixes may be sent
  668.  * to the author, who may or may not act on them as he desires.
  669.  *
  670.  * You may not include this software in a program or other software product
  671.  * without supplying the source, or without informing the end-user that the 
  672.  * source is available for no extra charge.
  673.  *
  674.  * If you modify this software, you should include a notice giving the
  675.  * name of the person performing the modification, the date of modification,
  676.  * and the reason for such modification.
  677.  */
  678. /* 
  679.  * rle_getcom.c - Get specific comments from globals structure.
  680.  * 
  681.  * Author:    Spencer W. Thomas
  682.  *         Computer Science Dept.
  683.  *         University of Utah
  684.  * Date:    Sun Jan 25 1987
  685.  * Copyright (c) 1987, University of Utah
  686.  */
  687.  
  688. /*****************************************************************
  689.  * TAG( match )
  690.  * 
  691.  * Match a name against a test string for "name=value" or "name".
  692.  * If it matches name=value, return pointer to value part, if just
  693.  * name, return pointer to NUL at end of string.  If no match, return NULL.
  694.  *
  695.  * Inputs:
  696.  *     n:    Name to match.  May also be "name=value" to make it easier
  697.  *        to replace comments.
  698.  *    v:    Test string.
  699.  * Outputs:
  700.  *     Returns pointer as above.
  701.  * Assumptions:
  702.  *    [None]
  703.  * Algorithm:
  704.  *    [None]
  705.  */
  706. static char *
  707. match( n, v )
  708. register char *n;
  709. register char *v;
  710. {
  711.     for ( ; *n != '\0' && *n != '=' && *n == *v; n++, v++ )
  712.     ;
  713.     if (*n == '\0' || *n == '=')
  714.     if ( *v == '\0' )
  715.         return v;
  716.     else if ( *v == '=' )
  717.         return ++v;
  718.  
  719.     return NULL;
  720. }
  721.  
  722. /*****************************************************************
  723.  * TAG( rle_getcom )
  724.  * 
  725.  * Return a pointer to the value part of a name=value pair in the comments.
  726.  * Inputs:
  727.  *     name:        Name part of the comment to search for.
  728.  *    globals:    sv_globals structure.
  729.  * Outputs:
  730.  *     Returns pointer to value part of comment or NULL if no match.
  731.  * Assumptions:
  732.  *    [None]
  733.  * Algorithm:
  734.  *    [None]
  735.  */
  736. char *
  737. rle_getcom( name, globals )
  738. char *name;
  739. struct sv_globals *globals;
  740. {
  741.     char ** cp;
  742.     char * v;
  743.  
  744.     if ( globals->sv_comments == NULL )
  745.     return NULL;
  746.  
  747.     for ( cp = globals->sv_comments; *cp; cp++ )
  748.     if ( (v = match( name, *cp )) != NULL )
  749.         return v;
  750.  
  751.     return NULL;
  752. }
  753.  
  754. /*
  755.  * This software is copyrighted as noted below.  It may be freely copied,
  756.  * modified, and redistributed, provided that the copyright notice is 
  757.  * preserved on all copies.
  758.  * 
  759.  * There is no warranty or other guarantee of fitness for this software,
  760.  * it is provided solely "as is".  Bug reports or fixes may be sent
  761.  * to the author, who may or may not act on them as he desires.
  762.  *
  763.  * You may not include this software in a program or other software product
  764.  * without supplying the source, or without informing the end-user that the 
  765.  * source is available for no extra charge.
  766.  *
  767.  * If you modify this software, you should include a notice giving the
  768.  * name of the person performing the modification, the date of modification,
  769.  * and the reason for such modification.
  770.  *
  771.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  772.  *  to have all "void" functions so declared.
  773.  */
  774. /* 
  775.  * rle_getrow.c - Read an RLE file in.
  776.  * 
  777.  * Author:    Spencer W. Thomas
  778.  *         Computer Science Dept.
  779.  *         University of Utah
  780.  * Date:    Wed Apr 10 1985
  781.  * Copyright (c) 1985 Spencer W. Thomas
  782.  * 
  783.  */
  784. /*
  785.  * Automatically define LITTLE_ENDIAN on vax and pdp11 machines
  786.  */
  787. #if defined(vax) || defined(pdp11)
  788. #define    LITTLE_ENDIAN
  789. #endif
  790.  
  791. struct inst {
  792.   unsigned opcode:8, datum:8;
  793. };
  794.  
  795. #define BREAD(type, var, len)\
  796.         zread( infile, (byte *)&var,len )
  797. #define OPCODE(inst) (inst.opcode & ~LONG)
  798. #define LONGP(inst) (inst.opcode & LONG)
  799. #define DATUM(inst) (0x00ff & inst.datum)
  800.  
  801. static int       debug_f;        /* if non-zero, print debug info */
  802. static void    bfill();
  803.  
  804. /*****************************************************************
  805.  * TAG( rle_get_setup )
  806.  * 
  807.  * Read the initialization information from an RLE file.
  808.  * Inputs:
  809.  *     globals:    Contains pointer to the input file.
  810.  * Outputs:
  811.  *     globals:    Initialized with information from the
  812.  *            input file.
  813.  *    Returns 0 on success, -1 if the file is not an RLE file,
  814.  *    -2 if malloc of the color map failed, -3 if an immediate EOF
  815.  *    is hit (empty input file), and -4 if an EOF is encountered reading
  816.  *    the setup information.
  817.  * Assumptions:
  818.  *     infile points to the "magic" number in an RLE file (usually
  819.  * byte 0 in the file).
  820.  * Algorithm:
  821.  *     Read in the setup info and fill in sv_globals.
  822.  */
  823. rle_get_setup( globals )
  824. struct sv_globals * globals;
  825. {
  826.     struct XtndRsetup setup;
  827.     short magic;            /* assume 16 bits */
  828.     register ZFILE *infile = globals->svfb_fd;
  829.     rle_pixel * bg_color;
  830.     register int i;
  831.     char * comment_buf;
  832.  
  833.     zclearerr(infile);
  834.     BREAD( short, magic, sizeof magic );
  835.     SWAB(magic);
  836.     if ( zeof( infile ) )
  837.     return -3;
  838.     if ( magic != XtndRMAGIC )
  839.     return -1;
  840.     BREAD( struct XtndRsetup, setup, SETUPSIZE );  /* assume VAX packing */
  841.     if ( zeof( infile ) )
  842.     return -4;
  843.     SWAB( setup.h_xpos );
  844.     SWAB( setup.h_ypos );
  845.     SWAB( setup.h_xlen );
  846.     SWAB( setup.h_ylen );
  847.  
  848.     /* Extract information from setup */
  849.     globals->sv_ncolors = setup.h_ncolors;
  850.     for ( i = 0; i < globals->sv_ncolors; i++ )
  851.     SV_SET_BIT( *globals, i );
  852.  
  853.     if ( !(setup.h_flags & H_NO_BACKGROUND) )
  854.     {
  855.     globals->sv_bg_color = (int *)lmalloc(
  856.         (unsigned)(sizeof(int) * setup.h_ncolors) );
  857.     bg_color = (rle_pixel *)lmalloc(
  858.         (unsigned)(1 + (setup.h_ncolors / 2) * 2) );
  859.     zread( infile, (byte *)bg_color, 1 + (setup.h_ncolors / 2) * 2 );
  860.     for ( i = 0; i < setup.h_ncolors; i++ )
  861.         globals->sv_bg_color[i] = bg_color[i];
  862.     lfree( bg_color );
  863.     }
  864.     else
  865.     zgetc( infile );            /* skip filler byte */
  866.  
  867.     if ( setup.h_flags & H_NO_BACKGROUND )
  868.     globals->sv_background = 0;
  869.     else if ( setup.h_flags & H_CLEARFIRST )
  870.     globals->sv_background = 2;
  871.     else
  872.     globals->sv_background = 1;
  873.     if ( setup.h_flags & H_ALPHA )
  874.     {
  875.     globals->sv_alpha = 1;
  876.     SV_SET_BIT( *globals, SV_ALPHA );
  877.     }
  878.     else
  879.     globals->sv_alpha = 0;
  880.  
  881.     globals->sv_xmin = setup.h_xpos;
  882.     globals->sv_ymin = setup.h_ypos;
  883.     globals->sv_xmax = globals->sv_xmin + setup.h_xlen - 1;
  884.     globals->sv_ymax = globals->sv_ymin + setup.h_ylen - 1;
  885.  
  886.     globals->sv_ncmap = setup.h_ncmap;
  887.     globals->sv_cmaplen = setup.h_cmaplen;
  888.     if ( globals->sv_ncmap > 0 )
  889.     {
  890.     register int maplen =
  891.              globals->sv_ncmap * (1 << globals->sv_cmaplen);
  892.     globals->sv_cmap = (rle_map *)lmalloc(
  893.         (unsigned)(sizeof(rle_map) * maplen) );
  894.     if ( globals->sv_cmap == NULL )
  895.     {
  896.         fprintf( stderr,
  897.         "Malloc failed for color map of size %d*%d in rle_get_setup\n",
  898.         globals->sv_ncmap, (1 << globals->sv_cmaplen) );
  899.         return -2;
  900.     }
  901.     zread( infile, (byte *)globals->sv_cmap, sizeof(short) * maplen );
  902. #ifndef LITTLE_ENDIAN
  903.         /* Swap bytes on bigendian machines
  904.      */
  905.         for ( i = 0; i < maplen; i++ )
  906.             SWAB( globals->sv_cmap[i] );
  907. #endif
  908.     }
  909.  
  910.     /* Check for comments */
  911.     if ( setup.h_flags & H_COMMENT )
  912.     {
  913.     short comlen, evenlen;
  914.     register char * cp;
  915.  
  916.     BREAD( short, comlen, sizeof comlen );    /* get comment length */
  917.     SWAB( comlen );
  918.     evenlen = (comlen + 1) & ~1;    /* make it even */
  919.     comment_buf = (char *)lmalloc( (unsigned) evenlen );
  920.     if ( comment_buf == NULL )
  921.     {
  922.         fprintf( stderr,
  923.              "Malloc failed for comment buffer of size %d in rle_get_setup\n",
  924.              comlen );
  925.         return -2;
  926.     }
  927.     zread( infile, (byte *)comment_buf, evenlen );
  928.     /* Count the comments */
  929.     for ( i = 0, cp = comment_buf; cp < comment_buf + comlen; cp++ )
  930.         if ( *cp == 0 )
  931.         i++;
  932.     i++;            /* extra for NULL pointer at end */
  933.     /* Get space to put pointers to comments */
  934.     globals->sv_comments =
  935.         (char **)lmalloc( (unsigned)(i * sizeof(char *)) );
  936.     if ( globals->sv_comments == NULL )
  937.     {
  938.         fprintf( stderr,
  939.             "Malloc failed for %d comment pointers in rle_get_setup\n",
  940.              i );
  941.         return -2;
  942.     }
  943.     /* Get pointers to the comments */
  944.     *globals->sv_comments = comment_buf;
  945.     for ( i = 1, cp = comment_buf + 1; cp < comment_buf + comlen; cp++ )
  946.         if ( *(cp - 1) == 0 )
  947.         globals->sv_comments[i++] = cp;
  948.     globals->sv_comments[i] = NULL;
  949.     }
  950.     else
  951.     globals->sv_comments = NULL;
  952.  
  953.     /* Initialize state for rle_getrow */
  954.     globals->sv_private.get.scan_y = globals->sv_ymin;
  955.     globals->sv_private.get.vert_skip = 0;
  956.     globals->sv_private.get.is_eof = 0;
  957.     globals->sv_private.get.is_seek = 0;    /* Can't do seek on zfile */
  958.     debug_f = 0;
  959.  
  960.     if ( !zeof( infile ) )
  961.     return 0;            /* success! */
  962.     else
  963.     {
  964.     globals->sv_private.get.is_eof = 1;
  965.     return -4;
  966.     }
  967. }
  968.  
  969.  
  970. /*****************************************************************
  971.  * TAG( rle_get_error )
  972.  * 
  973.  * Print an error message for the return code from rle_get_setup
  974.  * Inputs:
  975.  *     code:        The return code from rle_get_setup.
  976.  *    pgmname:    Name of this program (argv[0]).
  977.  *    fname:        Name of the input file.
  978.  * Outputs:
  979.  *     Prints an error message on standard output.
  980.  *    Returns code.
  981.  */
  982.  
  983. rle_get_error( code, pgmname, fname )
  984. char *pgmname;
  985. char *fname;
  986. {
  987.     switch( code )
  988.     {
  989.     case 0:            /* success */
  990.     break;
  991.  
  992.     case -1:            /* Not an RLE file */
  993.     fprintf( stderr, "%s: %s is not an RLE file\n",
  994.          pgmname, fname );
  995.     break;
  996.  
  997.     case -2:            /* malloc failed */
  998.     fprintf( stderr,
  999.          "%s: Malloc failed reading header of file %s\n",
  1000.          pgmname, fname );
  1001.     break;
  1002.  
  1003.     case -3:
  1004.     fprintf( stderr, "%s: %s is an empty file\n", pgmname, fname );
  1005.     break;
  1006.  
  1007.     case -4:
  1008.     fprintf( stderr,
  1009.          "%s: RLE header of %s is incomplete (premature EOF)\n",
  1010.          pgmname, fname );
  1011.     break;
  1012.  
  1013.     default:
  1014.     fprintf( stderr, "%s: Error encountered reading header of %s\n",
  1015.          pgmname, fname );
  1016.     break;
  1017.     }
  1018.     return code;
  1019. }
  1020.  
  1021.  
  1022. /*****************************************************************
  1023.  * TAG( rle_get_setup_ok )
  1024.  * 
  1025.  * Read the initialization information from an RLE file.
  1026.  * Inputs:
  1027.  *     globals:    Contains pointer to the input file.
  1028.  *    prog_name:  Program name to be printed in the error message.
  1029.  *      file_name:  File name to be printed in the error message.
  1030.  *                  If NULL, the string "stdin" is generated.
  1031.  * Outputs:
  1032.  *     globals:    Initialized with information from the
  1033.  *            input file.
  1034.  *      If reading the globals fails, it prints an error message
  1035.  *    and exits with the appropriate status code.
  1036.  * Algorithm:
  1037.  *     sv_get_setup does all the work.
  1038.  */
  1039. void
  1040. rle_get_setup_ok( globals, prog_name, file_name )
  1041. struct sv_globals * globals;
  1042. char *prog_name;
  1043. char *file_name;
  1044. {
  1045.     int code;
  1046.  
  1047.     if (! file_name)
  1048.     file_name = "stdin";
  1049.  
  1050.     code = rle_get_error( rle_get_setup( globals ), prog_name, file_name );
  1051.     if (code)
  1052.     exit( code );
  1053. }
  1054.  
  1055.  
  1056. /*****************************************************************
  1057.  * TAG( rle_debug )
  1058.  * 
  1059.  * Turn RLE debugging on or off.
  1060.  * Inputs:
  1061.  *     on_off:        if 0, stop debugging, else start.
  1062.  * Outputs:
  1063.  *     Sets internal debug flag.
  1064.  * Assumptions:
  1065.  *    [None]
  1066.  * Algorithm:
  1067.  *    [None]
  1068.  */
  1069. void
  1070. rle_debug( on_off )
  1071. int on_off;
  1072. {
  1073.     debug_f = on_off;
  1074. }
  1075.  
  1076.  
  1077. /*****************************************************************
  1078.  * TAG( rle_getrow )
  1079.  * 
  1080.  * Get a scanline from the input file.
  1081.  * Inputs:
  1082.  *    globals:    sv_globals structure containing information about 
  1083.  *            the input file.
  1084.  * Outputs:
  1085.  *     scanline:   an array of pointers to the individual color
  1086.  *            scanlines.  Scanline is assumed to have
  1087.  *            globals->sv_ncolors pointers to arrays of rle_pixel,
  1088.  *            each of which is at least globals->sv_xmax+1 long.
  1089.  *    Returns the current scanline number.
  1090.  * Assumptions:
  1091.  *     rle_get_setup has already been called.
  1092.  * Algorithm:
  1093.  *     If a vertical skip is being executed, and clear-to-background is
  1094.  *    specified (globals->sv_background is true), just set the
  1095.  *    scanlines to the background color.  If clear-to-background is
  1096.  *    not set, just increment the scanline number and return.
  1097.  * 
  1098.  *    Otherwise, read input until a vertical skip is encountered,
  1099.  *    decoding the instructions into scanline data.
  1100.  */
  1101.  
  1102. rle_getrow( globals, scanline )
  1103. struct sv_globals * globals;
  1104. rle_pixel *scanline[];
  1105. {
  1106.     register rle_pixel * scanc;
  1107.     register int nc;
  1108.     register ZFILE *infile = globals->svfb_fd;
  1109.     int scan_x = globals->sv_xmin,    /* current X position */
  1110.        channel = 0;            /* current color channel */
  1111.     short word, long_data;
  1112.     struct inst inst;
  1113.  
  1114.     /* Clear to background if specified */
  1115.     if ( globals->sv_background == 2 )
  1116.     {
  1117.     if ( globals->sv_alpha && SV_BIT( *globals, -1 ) )
  1118.         bfill( (char *)scanline[-1], globals->sv_xmax + 1, 0 );
  1119.     for ( nc = 0; nc < globals->sv_ncolors; nc++ )
  1120.         if ( SV_BIT( *globals, nc ) )
  1121.         bfill( (char *)scanline[nc], globals->sv_xmax+1,
  1122.             globals->sv_bg_color[nc] );
  1123.     }
  1124.  
  1125.     /* If skipping, then just return */
  1126.     if ( globals->sv_private.get.vert_skip > 0 )
  1127.     {
  1128.     globals->sv_private.get.vert_skip--;
  1129.     globals->sv_private.get.scan_y++;
  1130.     if ( globals->sv_private.get.vert_skip > 0 )
  1131.         return globals->sv_private.get.scan_y;
  1132.     }
  1133.  
  1134.     /* If EOF has been encountered, return also */
  1135.     if ( globals->sv_private.get.is_eof )
  1136.     return ++globals->sv_private.get.scan_y;
  1137.  
  1138.     /* Otherwise, read and interpret instructions until a skipLines
  1139.      * instruction is encountered.
  1140.      */
  1141.     if ( SV_BIT( *globals, channel ) )
  1142.     scanc = scanline[channel] + scan_x;
  1143.     else
  1144.     scanc = NULL;
  1145.     for (;;)
  1146.     {
  1147.         BREAD(struct inst, inst, 2 );
  1148.     if ( zeof(infile) )
  1149.     {
  1150.         globals->sv_private.get.is_eof = 1;
  1151.         break;        /* <--- one of the exits */
  1152.     }
  1153.  
  1154.     switch( OPCODE(inst) )
  1155.     {
  1156.     case RSkipLinesOp:
  1157.         if ( LONGP(inst) )
  1158.         {
  1159.             BREAD( short, long_data, sizeof long_data );
  1160.         SWAB( long_data );
  1161.         globals->sv_private.get.vert_skip = long_data;
  1162.         }
  1163.         else
  1164.         globals->sv_private.get.vert_skip = DATUM(inst);
  1165.         if (debug_f)
  1166.         fprintf(stderr, "Skip %d Lines (to %d)\n",
  1167.             globals->sv_private.get.vert_skip,
  1168.             globals->sv_private.get.scan_y +
  1169.                 globals->sv_private.get.vert_skip );
  1170.  
  1171.         break;            /* need to break for() here, too */
  1172.  
  1173.     case RSetColorOp:
  1174.         channel = DATUM(inst);    /* select color channel */
  1175.         if ( channel == 255 )
  1176.         channel = -1;
  1177.         scan_x = globals->sv_xmin;
  1178.         if ( SV_BIT( *globals, channel ) )
  1179.         scanc = scanline[channel]+scan_x;
  1180.         if ( debug_f )
  1181.         fprintf( stderr, "Set color to %d (reset x to %d)\n",
  1182.              channel, scan_x );
  1183.         break;
  1184.  
  1185.     case RSkipPixelsOp:
  1186.         if ( LONGP(inst) )
  1187.         {
  1188.             BREAD( short, long_data, sizeof long_data );
  1189.         SWAB( long_data );
  1190.         scan_x += long_data;
  1191.         scanc += long_data;
  1192.         if ( debug_f )
  1193.             fprintf( stderr, "Skip %d pixels (to %d)\n",
  1194.                 long_data, scan_x );
  1195.              
  1196.         }
  1197.         else
  1198.         {
  1199.         scan_x += DATUM(inst);
  1200.         scanc += DATUM(inst);
  1201.         if ( debug_f )
  1202.             fprintf( stderr, "Skip %d pixels (to %d)\n",
  1203.                 DATUM(inst), scan_x );
  1204.         }
  1205.         break;
  1206.  
  1207.     case RByteDataOp:
  1208.         if ( LONGP(inst) )
  1209.         {
  1210.             BREAD( short, long_data, sizeof long_data );
  1211.         SWAB( long_data );
  1212.         nc = (int)long_data;
  1213.         }
  1214.         else
  1215.         nc = DATUM(inst);
  1216.         nc++;
  1217.         if ( SV_BIT( *globals, channel ) )
  1218.         {
  1219.         zread( infile, (byte *)scanc, nc );
  1220.         if ( nc & 1 )
  1221.             (void)zgetc( infile );    /* throw away odd byte */
  1222.         }
  1223.         else
  1224.         {        /* Emulate a forward fseek */
  1225.             register int ii;
  1226.             for ( ii = ((nc + 1) / 2) * 2; ii > 0; ii-- )
  1227.             (void) zgetc( infile );    /* discard it */
  1228.         }
  1229.  
  1230.         scanc += nc;
  1231.         scan_x += nc;
  1232.         if ( debug_f )
  1233.         if ( SV_BIT( *globals, channel ) )
  1234.         {
  1235.             rle_pixel * cp = scanc - nc;
  1236.             fprintf( stderr, "Pixel data %d (to %d):", nc, scan_x );
  1237.             for ( ; nc > 0; nc-- )
  1238.             fprintf( stderr, "%02x", *cp++ );
  1239.             putc( '\n', stderr );
  1240.         }
  1241.         else
  1242.         fprintf( stderr, "Pixel data %d (to %d)\n", nc, scan_x );
  1243.         break;
  1244.  
  1245.     case RRunDataOp:
  1246.         if ( LONGP(inst) )
  1247.         {
  1248.             BREAD( short, long_data, sizeof long_data );
  1249.         SWAB( long_data );
  1250.         nc = long_data;
  1251.         }
  1252.         else
  1253.         nc = DATUM(inst);
  1254.         scan_x += nc + 1;
  1255.  
  1256.         BREAD( short, word, sizeof(short) );
  1257.         SWAB( word );
  1258.         if ( debug_f )
  1259.         fprintf( stderr, "Run length %d (to %d), data %02x\n",
  1260.                 nc + 1, scan_x, word );
  1261.         if ( SV_BIT( *globals, channel ) )
  1262.         {
  1263.         if ( nc >= 10 )        /* break point for 785, anyway */
  1264.         {
  1265.             bfill( (char *)scanc, nc + 1, word );
  1266.             scanc += nc + 1;
  1267.         }
  1268.         else
  1269.             for ( ; nc >= 0; nc--, scanc++ )
  1270.             *scanc = word;
  1271.         }
  1272.         break;
  1273.  
  1274.     case REOFOp:
  1275.         globals->sv_private.get.is_eof = 1;
  1276.         break;
  1277.  
  1278.     default:
  1279.         fprintf( stderr,
  1280.              "rle_getrow: Unrecognized opcode: %d\n", inst.opcode );
  1281.         exit(1);
  1282.     }
  1283.     if ( OPCODE(inst) == RSkipLinesOp || OPCODE(inst) == REOFOp )
  1284.         break;            /* <--- the other loop exit */
  1285.     }
  1286.  
  1287.     return globals->sv_private.get.scan_y;
  1288. }
  1289.  
  1290.  
  1291. /* Fill buffer at s with n copies of character c.  N must be <= 65535*/
  1292. /* ARGSUSED */
  1293. static void bfill( s, n, c )
  1294. char *s;
  1295. int n, c;
  1296. {
  1297. #if defined(vax) && !defined(VMS)
  1298.     asm("   movc5   $0,*4(ap),12(ap),8(ap),*4(ap)");
  1299. #else
  1300.     while ( n-- > 0 )
  1301.     *s++ = c;
  1302. #endif
  1303. }
  1304.  
  1305. /*
  1306.  * This software is copyrighted as noted below.  It may be freely copied,
  1307.  * modified, and redistributed, provided that the copyright notice is 
  1308.  * preserved on all copies.
  1309.  * 
  1310.  * There is no warranty or other guarantee of fitness for this software,
  1311.  * it is provided solely "as is".  Bug reports or fixes may be sent
  1312.  * to the author, who may or may not act on them as he desires.
  1313.  *
  1314.  * You may not include this software in a program or other software product
  1315.  * without supplying the source, or without informing the end-user that the 
  1316.  * source is available for no extra charge.
  1317.  *
  1318.  * If you modify this software, you should include a notice giving the
  1319.  * name of the person performing the modification, the date of modification,
  1320.  * and the reason for such modification.
  1321.  *
  1322.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  1323.  *  to have all "void" functions so declared.
  1324.  *
  1325.  * Modified to generate an apropriate size dither map (ie 2x2, 4x4, 8x8
  1326.  * or 16x16) rather than use fixed 16x16 map. Use a large enough map 
  1327.  * to give a minimum of 128 effective levels rather than aiming for 256.
  1328.  * This should give less grainy pictures.
  1329.  * Two global variables can modify this:
  1330.  * dith_levels = 128 (default)
  1331.  * dith_np2 = 0    (default). Nonzero to enable non power of 2 dither mapping.
  1332.  * dith_size = actual dither matrix size chosen.
  1333.  *
  1334.  * Graeme Gill    3 June 88
  1335.  */
  1336.  
  1337. /* 
  1338.  * dither.c - Functions for RGB color dithering.
  1339.  * 
  1340.  * Author:    Spencer W. Thomas
  1341.  *         Computer Science Dept.
  1342.  *         University of Utah
  1343.  * Date:    Mon Feb  2 1987
  1344.  * Copyright (c) 1987, University of Utah
  1345.  */
  1346.  
  1347. void    make_square();
  1348.  
  1349. /* dither globals */
  1350. int dith_levels = 128;
  1351. int dith_np2 = 0;
  1352. int dith_size = 16;
  1353.  
  1354. /* basic dithering macro */
  1355. #define DMAP(v,x,y)    (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v])
  1356.  
  1357. /*****************************************************************
  1358.  * TAG( dithermap )
  1359.  * 
  1360.  * Create a color dithering map with a specified number of intensity levels.
  1361.  * Inputs:
  1362.  *     levels:        Intensity levels per primary.
  1363.  *    gamma:        Display gamma value.
  1364.  * Outputs:
  1365.  *     rgbmap:        Generated color map.
  1366.  *    divN:        "div" function for dithering.
  1367.  *    modN:        "mod" function for dithering.
  1368.  * Assumptions:
  1369.  *     rgbmap will hold levels^3 entries.
  1370.  * Algorithm:
  1371.  *    Compute gamma compensation map.
  1372.  *    N = 255.0 / (levels - 1) is number of pixel values per level.
  1373.  *    Compute rgbmap with red ramping fastest, green slower, and blue
  1374.  *    slowest (treat it as if it were rgbmap[levels][levels][levels][3]).
  1375.  *    Call make_square to get divN, modN, and magic
  1376.  *
  1377.  * Note:
  1378.  *    Call dithergb( x, y, r, g, b, levels, divN, modN, magic ) to get index
  1379.  *    into rgbmap for a given color/location pair, or use
  1380.  *        row = y % 16; col = x % 16;
  1381.  *        DMAP(v,col,row) =def (divN[v] + (modN[v]>magic[col][row] ? 1 : 0))
  1382.  *        DMAP(r,col,row) + DMAP(g,col,row)*levels + DMAP(b,col,row)*levels^2
  1383.  *    if you don't want function call overhead.
  1384.  */
  1385. void
  1386. dithermap( levels, gamma, rgbmap, divN, modN, magic )
  1387. double gamma;
  1388. int rgbmap[][3];
  1389. int divN[256];
  1390. int modN[256];
  1391. int magic[16][16];
  1392. {
  1393.     double N;
  1394.     register int i;
  1395.     int levelsq, levelsc;
  1396.     int gammamap[256];
  1397.     
  1398.     make_gamma(gamma,gammamap);
  1399.  
  1400.     levelsq = levels*levels;    /* squared */
  1401.     levelsc = levels*levelsq;    /* and cubed */
  1402.  
  1403.     N = 255.0 / (levels - 1);    /* Get size of each step */
  1404.  
  1405.     /* 
  1406.      * Set up the color map entries.
  1407.      */
  1408.     for(i = 0; i < levelsc; i++) {
  1409.     rgbmap[i][0] = gammamap[(int)(0.5 + (i%levels) * N)];
  1410.     rgbmap[i][1] = gammamap[(int)(0.5 + ((i/levels)%levels) * N)];
  1411.     rgbmap[i][2] = gammamap[(int)(0.5 + ((i/levelsq)%levels) * N)];
  1412.     }
  1413.  
  1414.     make_square( N, divN, modN, magic );
  1415. }
  1416.  
  1417.  
  1418. /*****************************************************************
  1419.  * TAG( bwdithermap )
  1420.  * 
  1421.  * Create a color dithering map with a specified number of intensity levels.
  1422.  * Inputs:
  1423.  *     levels:        Intensity levels.
  1424.  *    gamma:        Display gamma value.
  1425.  * Outputs:
  1426.  *     bwmap:        Generated black & white map.
  1427.  *    divN:        "div" function for dithering.
  1428.  *    modN:        "mod" function for dithering.
  1429.  * Assumptions:
  1430.  *     bwmap will hold levels entries.
  1431.  * Algorithm:
  1432.  *    Compute gamma compensation map.
  1433.  *    N = 255.0 / (levels - 1) is number of pixel values per level.
  1434.  *    Compute bwmap for levels entries.
  1435.  *    Call make_square to get divN, modN, and magic.
  1436.  * Note:
  1437.  *    Call ditherbw( x, y, val, divN, modN, magic ) to get index into 
  1438.  *    bwmap for a given color/location pair, or use
  1439.  *        row = y % 16; col = x % 16;
  1440.  *        divN[val] + (modN[val]>magic[col][row] ? 1 : 0)
  1441.  *    if you don't want function call overhead.
  1442.  *    On a 1-bit display, use
  1443.  *        divN[val] > magic[col][row] ? 1 : 0
  1444.  */
  1445. void
  1446. bwdithermap( levels, gamma, bwmap, divN, modN, magic )
  1447. double gamma;
  1448. int bwmap[];
  1449. int divN[256];
  1450. int modN[256];
  1451. int magic[16][16];
  1452. {
  1453.     double N;
  1454.     register int i;
  1455.     int gammamap[256];
  1456.     
  1457.     make_gamma(gamma,gammamap);
  1458.  
  1459.     N = 255.0 / (levels - 1);    /* Get size of each step */
  1460.  
  1461.     /* 
  1462.      * Set up the color map entries.
  1463.      */
  1464.     for(i = 0; i < levels; i++)
  1465.     bwmap[i] = gammamap[(int)(0.5 + i * N)];
  1466.  
  1467.     make_square( N, divN, modN, magic );
  1468. }
  1469.  
  1470.  
  1471. /*****************************************************************
  1472.  * TAG( make_square )
  1473.  * 
  1474.  * Build the magic square for a given number of levels.
  1475.  * Inputs:
  1476.  *     N:        Pixel values per level (255.0 / (levels-1)).
  1477.  * (global) dith_levels = 128 (default) - number of effective levels to aim for 
  1478.  * (global) dith_np2 = 0 (default) - non-zero if non power of two size is permissable.
  1479.  * Outputs:
  1480.  *     divN:        Integer value of pixval / N
  1481.  *    modN:        Integer remainder between pixval and divN[pixval]*N
  1482.  *    magic:        Magic square for dithering to N sublevels.
  1483.  * (global) dith_size = magic square size chosen.
  1484.  * Assumptions:
  1485.  *     
  1486.  * Algorithm:
  1487.  *    divN[pixval] = (int)(pixval / N) maps pixval to its appropriate level.
  1488.  *    modN[pixval] = pixval - (int)(N * divN[pixval]) maps pixval to
  1489.  *    its sublevel, and is used in the dithering computation.
  1490.  */
  1491. void
  1492. make_square( N, divN, modN, magic )
  1493. double N;
  1494. int divN[256];
  1495. int modN[256];
  1496. int magic[16][16] ;
  1497. {
  1498.     register int i, j, k, l;
  1499.     double magicfact;
  1500.  
  1501.     for ( i = 0; i < 256; i++ )
  1502.     {
  1503.     divN[i] = (int)(i / N);
  1504.     modN[i] = i - (int)(N * divN[i]);
  1505.     }
  1506.     modN[255] = 0;        /* always */
  1507.  
  1508.     /* figure out how big a square will give */
  1509.     /* the desired number of levels */
  1510.     if(dith_np2)
  1511.         for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size++ );
  1512.     else
  1513.         for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size *=2);
  1514.  
  1515.     /* make the basic square up */
  1516.     /* ( will have numbers 0 - size * size ) */
  1517.     make_magic(dith_size,magic);
  1518.     
  1519.     /* divN gives 0 - levels-1 */
  1520.     /* modN gives 0 - N-1 */
  1521.     /* dither is if(modN(pix) > magic[][] so */
  1522.     /* scale magic it to have levels 0 to N-2 */
  1523.     /* (ie takes account of magic square size allows size * size +1 levels */
  1524.  
  1525.     magicfact = (N-2)/((double)((dith_size * dith_size)-1));
  1526.     for(i=0;i<dith_size;i++)
  1527.     {
  1528.         for(j=0;j<dith_size;j++)
  1529.         {
  1530.             magic[i][j] = (int)(0.5 + magic[i][j] * magicfact);
  1531.         }
  1532.     }
  1533.  
  1534.     if(!dith_np2)    /* if we have power of 2 */
  1535.     {
  1536.         /* now replicate the size square we've chosen */  
  1537.         /* (and use a brick pattern) */
  1538.         for(k=0;k<16;k += dith_size)
  1539.         {
  1540.             for(l=k>0?0:dith_size;l<16;l += dith_size)
  1541.             {
  1542.                 for(i=0;i<dith_size;i++)
  1543.                 {
  1544.                     for(j=0;j<dith_size;j++)
  1545.                     {
  1546.                         magic[k+i][((l+k/2)+j)%16] = magic[i][j];
  1547.                     }
  1548.                 }
  1549.             }
  1550.         }
  1551.     }
  1552. }
  1553.  
  1554. int magic16x16[16][16] = 
  1555.     {
  1556.         {0,128,32,160,8,136,40,168,2,130,34,162,10,138,42,170},
  1557.         {192,64,224,96,200,72,232,104,194,66,226,98,202,74,234,106},
  1558.         {48,176,16,144,56,184,24,152,50,178,18,146,58,186,26,154},
  1559.         {240,112,208,80,248,120,216,88,242,114,210,82,250,122,218,90},
  1560.         {12,140,44,172,4,132,36,164,14,142,46,174,6,134,38,166},
  1561.         {204,76,236,108,196,68,228,100,206,78,238,110,198,70,230,102},
  1562.         {60,188,28,156,52,180,20,148,62,190,30,158,54,182,22,150},
  1563.         {252,124,220,92,244,116,212,84,254,126,222,94,246,118,214,86},
  1564.         {3,131,35,163,11,139,43,171,1,129,33,161,9,137,41,169},
  1565.         {195,67,227,99,203,75,235,107,193,65,225,97,201,73,233,105},
  1566.         {51,179,19,147,59,187,27,155,49,177,17,145,57,185,25,153},
  1567.         {243,115,211,83,251,123,219,91,241,113,209,81,249,121,217,89},
  1568.         {15,143,47,175,7,135,39,167,13,141,45,173,5,133,37,165},
  1569.         {207,79,239,111,199,71,231,103,205,77,237,109,197,69,229,101},
  1570.         {63,191,31,159,55,183,23,151,61,189,29,157,53,181,21,149},
  1571.         {255,127,223,95,247,119,215,87,253,125,221,93,245,117,213,85}
  1572.     };
  1573.  
  1574. /*****************************************************************
  1575.  * TAG( make_magic )
  1576.      * 
  1577.  * Create the magic square.
  1578.  * Inputs:
  1579.  *     size:        Order of the square
  1580.  *  magic:        Address of 16 x 16 magic square.
  1581.  * Outputs:
  1582.  *     Fills in the 16 x 16 magic square.
  1583.  * Assumptions:
  1584.  *     size is between 2 and 16
  1585.  * Algorithm:
  1586.  *     Chose sub cell of 16 by 16 magic square
  1587.      */
  1588. make_magic( size, magic )
  1589. int size;
  1590. int magic[16][16];
  1591. {
  1592.     int j,i,li,bi,bx,by;
  1593.     int xx,yy;
  1594.     int total;
  1595.  
  1596.     total = size * size;
  1597.  
  1598.     i = 0;
  1599.     li = -1;
  1600.     for(j=0;j<total;j++)    
  1601.     {
  1602.         bi = 256;
  1603.  
  1604.         for(xx=0;xx<size;xx++)
  1605.         {
  1606.             for(yy=0;yy<size;yy++)
  1607.             {
  1608.                 if(magic16x16[xx][yy] >li && magic16x16[xx][yy] < bi)
  1609.                 {
  1610.                     bx = xx;
  1611.                     by = yy;
  1612.                     bi = magic16x16[xx][yy];
  1613.                 }
  1614.             }
  1615.         }
  1616.         magic[bx][by] = i;
  1617.         i++;
  1618.         li = bi;
  1619.     }
  1620. }
  1621.  
  1622. /*****************************************************************
  1623.  * TAG( make_gamma )
  1624.  * 
  1625.  * Makes a gamma compenstation map.
  1626.  * Inputs:
  1627.  *  gamma:            desired gamma
  1628.  *     gammamap:        gamma mapping array
  1629.  * Outputs:
  1630.  *  Changes gamma array entries.
  1631.  */
  1632. make_gamma( gamma, gammamap )
  1633. double gamma;
  1634. int gammamap[256];
  1635. {
  1636.     register int i;
  1637.  
  1638.     for ( i = 0; i < 256; i++ )
  1639.         {
  1640. #ifdef BYTEBUG
  1641.         int byteb1;
  1642.         
  1643.         byteb1 = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma ));
  1644.         gammamap[i] = byteb1;
  1645. #else
  1646.         gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma ));
  1647. #endif
  1648.         }
  1649. }
  1650.  
  1651. /*****************************************************************
  1652.  * TAG( dithergb )
  1653.  * 
  1654.  * Return dithered RGB value.
  1655.  * Inputs:
  1656.  *     x:        X location on screen of this pixel.
  1657.  *    y:        Y location on screen of this pixel.
  1658.  *    r, g, b:    Color at this pixel (0 - 255 range).
  1659.  *    levels:        Number of levels in this map.
  1660.  *    divN, modN:    From dithermap.
  1661.  *    magic:        Magic square from dithermap.
  1662.  * Outputs:
  1663.  *     Returns color map index for dithered pixelv value.
  1664.  * Assumptions:
  1665.  *     divN, modN, magic were set up properly.
  1666.  * Algorithm:
  1667.  *     see "Note:" in dithermap comment.
  1668.  */
  1669. dithergb( x, y, r, g, b, levels, divN, modN, magic )
  1670. int divN[256];
  1671. int modN[256];
  1672. int magic[16][16];
  1673. {
  1674.     int col = x % 16, row = y % 16;
  1675.  
  1676.     return DMAP(r, col, row) +
  1677.     DMAP(g, col, row) * levels +
  1678.         DMAP(b, col, row) * levels*levels;
  1679. }
  1680.  
  1681.  
  1682. /*****************************************************************
  1683.  * TAG( ditherbw )
  1684.  * 
  1685.  * Return dithered black & white value.
  1686.  * Inputs:
  1687.  *     x:        X location on screen of this pixel.
  1688.  *    y:        Y location on screen of this pixel.
  1689.  *    val:        Intensity at this pixel (0 - 255 range).
  1690.  *    divN, modN:    From dithermap.
  1691.  *    magic:        Magic square from dithermap.
  1692.  * Outputs:
  1693.  *     Returns color map index for dithered pixel value.
  1694.  * Assumptions:
  1695.  *     divN, modN, magic were set up properly.
  1696.  * Algorithm:
  1697.  *     see "Note:" in bwdithermap comment.
  1698.  */
  1699. ditherbw( x, y, val, divN, modN, magic )
  1700. int divN[256];
  1701. int modN[256];
  1702. int magic[16][16];
  1703. {
  1704.     int col = x % 16, row = y % 16;
  1705.  
  1706.     return DMAP(val, col, row);
  1707. }
  1708.