home *** CD-ROM | disk | FTP | other *** search
- /*
- * This software is copyrighted as noted below. It may be freely copied,
- * modified, and redistributed, provided that the copyright notice is
- * preserved on all copies.
- *
- * There is no warranty or other guarantee of fitness for this software,
- * it is provided solely "as is". Bug reports or fixes may be sent
- * to the author, who may or may not act on them as he desires.
- *
- * You may not include this software in a program or other software product
- * without supplying the source, or without informing the end-user that the
- * source is available for no extra charge.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- *
- * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
- * to have all "void" functions so declared.
- */
- /*
- * rle_row_alc.c - Allocate buffers for rle_getrow/rle_putrow.
- *
- * Author: Spencer W. Thomas
- * Computer Science Dept.
- * University of Utah
- * Date: Fri Nov 14 1986
- * Copyright (c) 1986, Spencer W. Thomas
- */
-
- #include <stdio.h>
- #include <malloc.h>
- #include "rle_put.h"
-
- #include "raddecl.h"
-
- /*****************************************************************
- * TAG( rle_row_alloc )
- *
- * Allocate buffer space for use by rle_getrow and rle_putrow.
- * Inputs:
- * the_hdr: Header structure for RLE file to be read or
- * written.
- * Outputs:
- * scanp: Pointer to pointer to created scanline buffer.
- * This pointer is adjusted for the alpha channel,
- * if present.
- * Returns 0 for success, -1 if malloc failed.
- * Assumptions:
- * No input scanline will extend beyond the declared xmax endpoint.
- * Algorithm:
- * Count number of channels actually used (check bitmap).
- * Allocate nchan*rowlength pixels, allocate a buffer
- * to hold ncolors+alpha pointers, and give each channel
- * rowlength pixels. Rowlength is xmax + 1, to allow for rle_getrow
- * usage.
- */
- int rle_row_alloc( the_hdr, scanp )
- rle_hdr *the_hdr;
- rle_pixel ***scanp;
- {
- rle_pixel ** scanbuf, * pixbuf;
- int rowlen, nchan = 0, i, ncol;
-
- rowlen = the_hdr->xmax + 1;
- if ( the_hdr->alpha && RLE_BIT( *the_hdr, RLE_ALPHA ) )
- nchan++;
- for ( i = 0; i < the_hdr->ncolors; i++ )
- if ( RLE_BIT( *the_hdr, i ) )
- nchan++;
-
- ncol = the_hdr->ncolors + the_hdr->alpha;
-
- if ( (scanbuf = (rle_pixel **)malloc( ncol * sizeof(rle_pixel *) )) == 0 )
- return -1;
- if ( (pixbuf = (rle_pixel *)malloc( nchan * rowlen *
- sizeof(rle_pixel) )) == 0 )
- {
- free( scanbuf );
- return -1;
- }
-
- if ( the_hdr->alpha )
- scanbuf++;
-
- for ( i = -the_hdr->alpha; i < the_hdr->ncolors; i++ )
- if ( RLE_BIT( *the_hdr, i ) )
- {
- scanbuf[i] = pixbuf;
- pixbuf += rowlen;
- }
- else
- scanbuf[i] = 0;
- *scanp = scanbuf;
-
- return 0;
- }
-
-
- /*****************************************************************
- * TAG( rle_row_free )
- *
- * Free storage allocated by rle_row_alloc().
- * Inputs:
- * the_hdr: Header structure as above.
- * scanp: Pointer to scanbuf above.
- * Outputs:
- * Frees storage referenced by scanp and nrawp.
- * Assumptions:
- * Storage was allocated by rle_row_alloc, or by use of same
- * algorithm, at least.
- * Algorithm:
- * free scanp[0] and scanp.
- */
- void rle_row_free( the_hdr, scanp )
- rle_hdr *the_hdr;
- rle_pixel **scanp;
- {
- int i;
-
- if ( the_hdr->alpha )
- scanp--;
- for ( i = 0; i < the_hdr->ncolors + the_hdr->alpha; i++ )
- if ( scanp[i] != 0 )
- {
- free( (char *)scanp[i] );
- break;
- }
- free( (char *)scanp );
- }
- /*
- * This software is copyrighted as noted below. It may be freely copied,
- * modified, and redistributed, provided that the copyright notice is
- * preserved on all copies.
- *
- * There is no warranty or other guarantee of fitness for this software,
- * it is provided solely "as is". Bug reports or fixes may be sent
- * to the author, who may or may not act on them as he desires.
- *
- * You may not include this software in a program or other software product
- * without supplying the source, or without informing the end-user that the
- * source is available for no extra charge.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- *
- * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
- * to have all "void" functions so declared.
- */
- /*
- * rle_putrow.c - Save a row of the fb to a file.
- *
- * Author: Spencer W. Thomas
- * Computer Science Dept.
- * University of Utah
- * Date: 1 April 1981
- * Copyright (c) 1981,1986 Spencer W. Thomas
- *
- * $Id: rle_putrow.c,v 3.0.1.1 90/11/27 14:54:37 spencer Exp $
- */
-
- #ifdef USE_STDLIB_H
- #include <stdlib.h>
- #else
-
- #endif /* USE_STDLIB_H */
-
- static int findruns();
-
- #define FASTRUNS /* Faster run finding */
- #ifdef vax
- #define LOCC /* Use vax instructions for more speed */
- #endif
-
- #define FALSE 0
- #define TRUE 1
-
- /*****************************************************************
- * TAG( rle_putrow )
- * Write a scanline to the output file.
- *
- * Inputs:
- * rows: Pointer to vector of pointers to
- * rle_pixel arrays containing the pixel information.
- * If NULL, rowlen scanlines are skipped.
- * rowlen: The number of pixels in the scanline, or the
- * number of scanlines to skip (see above).
- * Outputs:
- * Run length encoded information is written to the_hdr.rle_file.
- * Assumptions:
- * I'm sure there are lots of assumptions in here.
- * Algorithm:
- * [read the code :-]
- */
-
- void rle_putrow(rows, rowlen, the_hdr)
- register rle_pixel *rows[];
- int rowlen;
- register rle_hdr * the_hdr;
- {
- register int i, j;
- int nrun;
- register rle_pixel *row;
- int mask;
- char bits[256];
- short state,
- dstart,
- dend,
- rstart = 0,
- runval = 0; /* shut up lint */
-
- if (rows == NULL)
- {
- the_hdr->priv.put.nblank += rowlen;
- return;
- }
- /*
- * If not done already, allocate space to remember runs of
- * non-background color. A run of bg color must be at least 2
- * bytes long to count, so there can be at most rowlen/3 of them.
- */
- if ( the_hdr->priv.put.brun == NULL )
- {
- the_hdr->priv.put.brun =
- (short (*)[2])malloc(
- (unsigned)((rowlen/3 + 1) * 2 * sizeof(short)) );
- if ( the_hdr->priv.put.brun == NULL )
- {
- fprintf( stderr, "Malloc failed in rle_putrow\n" );
- exit(1);
- }
- }
- /* Unpack bitmask in the_hdr struct */
- for ( i=0; i < the_hdr->ncolors; i++ )
- bits[i] = RLE_BIT( *the_hdr, i );
- bits[255] = RLE_BIT( *the_hdr, -1 );
-
- /*
- * If saving only non-background pixels, find runs of them. Note
- * that the alpha channel is considered to be background iff it is
- * zero.
- */
- #ifdef FASTRUNS
- if ( the_hdr->background )
- {
- /*
- * Find runs in each color individually, merging them as we go.
- */
- nrun = 0; /* start out with no runs */
- /* Alpha channel first */
- if ( the_hdr->alpha )
- nrun = findruns( rows[-1], rowlen, 0, nrun,
- the_hdr->priv.put.brun );
- /* Now the color channels */
- for ( i = 0; i < the_hdr->ncolors; i++ )
- if ( bits[i] )
- nrun = findruns( rows[i], rowlen, the_hdr->bg_color[i],
- nrun, the_hdr->priv.put.brun );
- }
- else
- {
- the_hdr->priv.put.brun[0][0] = 0;
- the_hdr->priv.put.brun[0][1] = rowlen-1;
- nrun = 1;
- }
- #else /* FASTRUNS */
- if (the_hdr->background) /* find non-background runs */
- {
- j = 0;
- for (i=0; i<rowlen; i++)
- if (!same_color( i, rows, the_hdr->bg_color,
- the_hdr->ncolors, bits ) ||
- (the_hdr->alpha && rows[-1][i] != 0))
- {
- if (j > 0 && i - the_hdr->priv.put.brun[j-1][1] <= 4)
- j--;
- else
- the_hdr->priv.put.brun[j][0] = i; /* start of run */
- for ( i++;
- i < rowlen &&
- ( !same_color( i, rows, the_hdr->bg_color,
- the_hdr->ncolors, bits ) ||
- (the_hdr->alpha && rows[-1][i] != 0) );
- i++)
- ; /* find the end of this run */
- the_hdr->priv.put.brun[j][1] = i-1; /* last in run */
- j++;
- }
- nrun = j;
- }
- else
- {
- the_hdr->priv.put.brun[0][0] = 0;
- the_hdr->priv.put.brun[0][1] = rowlen-1;
- nrun = 1;
- }
- #endif /* FASTRUNS */
- if (nrun > 0)
- {
- if (the_hdr->priv.put.nblank > 0)
- {
- SkipBlankLines(the_hdr->priv.put.nblank);
- the_hdr->priv.put.nblank = 0;
- }
- for ( mask = (the_hdr->alpha ? -1 : 0);
- mask < the_hdr->ncolors;
- mask++) /* do all colors */
- {
- if ( ! bits[mask & 0xff] )
- {
- continue;
- }
- row = rows[mask];
- SetColor(mask);
- if (the_hdr->priv.put.brun[0][0] > 0)
- {
- SkipPixels(the_hdr->priv.put.brun[0][0], FALSE, FALSE);
- }
- for (j=0; j<nrun; j++)
- {
- state = DATA;
- dstart = the_hdr->priv.put.brun[j][0];
- dend = the_hdr->priv.put.brun[j][1];
- for (i=dstart; i<=dend; i++)
- {
- switch(state)
- {
- case DATA:
- if (i > dstart && runval == row[i])
- {
- state = RUN2; /* 2 in a row, may be a run */
- }
- else
- {
- runval = row[i]; /* maybe a run starts here? */
- rstart = i;
- }
- break;
-
- case RUN2:
- if (runval == row[i])
- {
- state = RUN3; /* 3 in a row may be a run */
- }
- else
- {
- state = DATA; /* Nope, back to data */
- runval = row[i]; /* but maybe a new run here? */
- rstart = i;
- }
- break;
-
- case RUN3:
- if (runval == row[i]) /* 3 in a row is a run */
- {
- state = INRUN;
- putdata(row + dstart, rstart - dstart);
- #ifdef FASTRUNS
- #ifdef LOCC
- /* Shortcut to find end of run! */
- i = dend - skpc( (char *)row + i, dend + 1 - i,
- runval );
- #else
- while ( row[++i] == runval && i <= dend)
- ; /* not quite so good, but not bad */
- i--;
- #endif /* LOCC */
- #endif /* FASTRUNS */
- }
- else
- {
- state = DATA; /* not a run, */
- runval = row[i]; /* but may this starts one */
- rstart = i;
- }
- break;
-
- case INRUN:
- if (runval != row[i]) /* if run out */
- {
- state = DATA;
- putrun(runval, i - rstart, FALSE);
- runval = row[i]; /* who knows, might be more */
- rstart = i;
- dstart = i; /* starting a new 'data' run */
- }
- break;
- }
- }
- if (state == INRUN)
- putrun(runval, i - rstart, TRUE); /* last bit */
- else
- putdata(row + dstart, i - dstart);
-
- if (j < nrun-1)
- SkipPixels(
- the_hdr->priv.put.brun[j+1][0] - dend - 1,
- FALSE, state == INRUN);
- else
- {
- if (rowlen - dend > 0)
- SkipPixels(
- rowlen - dend - 1,
- TRUE, state == INRUN);
- }
- }
-
- if ( mask != the_hdr->ncolors - 1 )
- NewScanLine(FALSE);
- }
- }
-
- /* Increment to next scanline */
- the_hdr->priv.put.nblank++;
-
- /* flush every scanline */
- fflush( the_hdr->rle_file );
- }
-
- /*****************************************************************
- * TAG( rle_put_init )
- *
- * Initialize the header structure for writing scanlines.
- * Inputs:
- * [None]
- * Outputs:
- * the_hdr: Private portions initialized for output.
- * Assumptions:
- * [None]
- * Algorithm:
- * [None]
- */
- void rle_put_init( the_hdr )
- register rle_hdr *the_hdr;
- {
- the_hdr->dispatch = RUN_DISPATCH;
- the_hdr->priv.put.nblank = 0; /* Reinit static vars */
- /* Would like to be able to free previously allocated storage,
- * but can't count on a non-NULL value being a valid pointer.
- */
- the_hdr->priv.put.brun = NULL;
- the_hdr->priv.put.fileptr = 0;
-
- /* Only save alpha if alpha AND alpha channel bit are set. */
- if ( the_hdr->alpha )
- the_hdr->alpha = (RLE_BIT( *the_hdr, -1 ) != 0);
- else
- RLE_CLR_BIT( *the_hdr, -1 );
- }
-
- /*****************************************************************
- * TAG( rle_put_setup )
- *
- * Initialize for writing RLE, and write header to output file.
- * Inputs:
- * the_hdr: Describes output image.
- * Outputs:
- * the_hdr: Initialized.
- * Assumptions:
- * Lots of them.
- * Algorithm:
- * [None]
- */
- void rle_put_setup( the_hdr )
- register rle_hdr * the_hdr;
- {
- rle_put_init( the_hdr );
- Setup();
- }
-
- /*ARGSUSED*/
- int DefaultBlockHook(the_hdr)
- rle_hdr * the_hdr;
- {
- /* Do nothing */
- }
-
- /*****************************************************************
- * TAG( rle_puteof )
- * Write an EOF code into the output file.
- */
- void rle_puteof( the_hdr )
- register rle_hdr * the_hdr;
- {
- /* Don't puteof twice. */
- if ( the_hdr->dispatch == NO_DISPATCH )
- return;
- PutEof();
- fflush( the_hdr->rle_file );
- /* Free storage allocated by rle_put_init. */
- if ( the_hdr->priv.put.brun != NULL )
- {
- free( the_hdr->priv.put.brun );
- the_hdr->priv.put.brun = NULL;
- }
- /* Signal that puteof has been called. */
- the_hdr->dispatch = NO_DISPATCH;
- }
-
- #ifndef FASTRUNS
- /*****************************************************************
- * TAG( same_color )
- *
- * Determine if the color at the given index position in the scan rows
- * is the same as the background color.
- * Inputs:
- * index: Index to the pixel position in each row.
- * rows: array of pointers to the scanlines
- * bg_color: the background color
- * ncolors: number of color elements/pixel
- * Outputs:
- * TRUE if the color at row[*][i] is the same as bg_color[*].
- * Assumptions:
- * [None]
- * Algorithm:
- * [None]
- */
- static int
- same_color( index, rows, bg_color, ncolors, bits )
- register rle_pixel *rows[];
- register int bg_color[];
- char *bits;
- {
- register int i;
-
- for ( i = 0; i < ncolors; i++, bits++ )
- if ( *bits &&
- rows[i][index] != bg_color[i] )
- return 0;
- return 1; /* all the same */
- }
- #endif /* !FASTRUNS */
-
- /*****************************************************************
- * TAG( findruns )
- *
- * Find runs not a given color in the row.
- * Inputs:
- * row: Row of pixel values
- * rowlen: Number of pixels in the row.
- * color: Color to compare against.
- * nrun: Number of runs already found (in different colors).
- * brun: Runs found in other color channels already.
- * Outputs:
- * brun: Modified to reflect merging of runs in this color.
- * Returns number of runs in brun.
- * Assumptions:
- *
- * Algorithm:
- * Search for occurences of pixels not of the given color outside the
- * runs already found. When some are found, add a new run or extend
- * an existing one. Adjacent runs with fewer than two pixels intervening
- * are merged.
- */
- static int findruns( row, rowlen, color, nrun, brun )
- register rle_pixel *row;
- int rowlen, color, nrun;
- short (*brun)[2];
- {
- int i = 0, lower, upper;
- register int s, j;
-
- #ifdef DEBUG
- fprintf( stderr, "findruns( " );
- for ( s = 0; s < rowlen; s++ )
- fprintf( stderr, "%2x.%s", row[s], (s % 20 == 19) ? "\n\t" : "" );
- if ( s % 20 != 0 )
- fprintf( stderr, "\n\t" );
- fprintf( stderr, "%d, %d, %d, \n\t", rowlen, color, nrun );
- for ( j = 0; j < nrun; j++ )
- fprintf( stderr, "(%3d,%3d) %s", brun[j][0], brun[j][1],
- (j % 6 == 5) ? "\n\t" : "" );
- fprintf( stderr, ")\n" );
- #endif
-
- while ( i <= nrun )
- {
- /* Assert: 0 <= i <= rowlen
- * brun[i] is the run following the "blank" space being
- * searched. If i == rowlen, search after brun[i-1].
- */
-
- /* get lower and upper bounds of search */
-
- if ( i == 0 )
- lower = 0;
- else
- lower = brun[i-1][1] + 1;
-
- if ( i == nrun )
- upper = rowlen - 1;
- else
- upper = brun[i][0] - 1;
-
- #ifdef DEBUG
- fprintf( stderr, "Searching before run %d from %d to %d\n",
- i, lower, upper );
- #endif
- /* Search for beginning of run != color */
- #if defined(LOCC)&defined(vax)
- s = upper - skpc( (char *)row + lower, upper - lower + 1, color ) + 1;
- #else
- for ( s = lower; s <= upper; s++ )
- if ( row[s] != color )
- break;
- #endif
-
- if ( s <= upper ) /* found a new run? */
- {
- if ( s > lower + 1 || i == 0 ) /* disjoint from preceding run? */
- {
- #ifdef DEBUG
- fprintf( stderr, "Found new run starting at %d\n", s );
- #endif
- /* Shift following runs up */
- for ( j = nrun; j > i; j-- )
- {
- brun[j][0] = brun[j-1][0];
- brun[j][1] = brun[j-1][1];
- }
- brun[i][0] = s;
- nrun++;
- }
- else
- {
- i--; /* just add to preceding run */
- #ifdef DEBUG
- fprintf( stderr, "Adding to previous run\n" );
- #endif
- }
-
- #if defined(LOCC)&defined(vax)
- s = upper - locc( (char *)row + s, upper - s + 1, color ) + 1;
- #else
- for ( ; s <= upper; s++ )
- if ( row[s] == color )
- break;
- #endif
- brun[i][1] = s - 1;
-
- #ifdef DEBUG
- fprintf( stderr, "Ends at %d", s - 1 );
- #endif
- if ( s >= upper && i < nrun - 1 ) /* merge with following run */
- {
- brun[i][1] = brun[i+1][1];
- /* move following runs back down */
- for ( j = i + 2; j < nrun; j++ )
- {
- brun[j-1][0] = brun[j][0];
- brun[j-1][1] = brun[j][1];
- }
- nrun--;
- #ifdef DEBUG
- fprintf( stderr, ", add to next run" );
- #endif
- }
- #ifdef DEBUG
- putc( '\n', stderr );
- #endif
- }
-
- /* Search in next space */
- i++;
- }
-
- return nrun;
- }
-
- #ifdef LOCC
- /*ARGSUSED*/
- int locc( p, l, c )
- register char *p;
- register int l;
- register int c;
- {
- asm( "locc r9,r10,(r11)" );
- #ifdef lint
- c = (int) p; /* why doesn't ARGSUSED work? */
- l = c;
- return l; /* Needs return value, at least */
- #endif
- }
-
- /*ARGSUSED*/
- int skpc( p, l, c )
- register char *p;
- register int l;
- register int c;
- {
- asm( "skpc r9,r10,(r11)" );
- #ifdef lint
- c = (int) p; /* why doesn't ARGSUSED work? */
- l = c;
- return l; /* Needs return value, at least */
- #endif
- }
- #endif
- /*
- * This software is copyrighted as noted below. It may be freely copied,
- * modified, and redistributed, provided that the copyright notice is
- * preserved on all copies.
- *
- * There is no warranty or other guarantee of fitness for this software,
- * it is provided solely "as is". Bug reports or fixes may be sent
- * to the author, who may or may not act on them as he desires.
- *
- * You may not include this software in a program or other software product
- * without supplying the source, or without informing the end-user that the
- * source is available for no extra charge.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- *
- * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
- * to have all "void" functions so declared.
- */
- /*
- * rle_global.c - Global variable initialization for rle routines.
- *
- * Author: Spencer W. Thomas
- * Computer Science Dept.
- * University of Utah
- * Date: Thu Apr 25 1985
- * Copyright (c) 1985,1986 Spencer W. Thomas
- *
- * $Id: rle_global.c,v 3.0 90/08/03 15:20:54 spencer Exp $
- */
-
- extern int RunSetup( ARB_ARGS ),
- RunSkipBlankLines( ARB_ARGS ),
- RunSetColor( ARB_ARGS ),
- RunSkipPixels( ARB_ARGS ),
- RunNewScanLine( ARB_ARGS ),
- Runputdata( ARB_ARGS ),
- Runputrun( ARB_ARGS ),
- RunputEof( ARB_ARGS );
-
- extern void NullputEof( ARB_ARGS );
-
- struct rle_dispatch_tab rle_DTable[] = {
- {
- " OB",
- RunSetup,
- RunSkipBlankLines,
- RunSetColor,
- RunSkipPixels,
- RunNewScanLine,
- Runputdata,
- Runputrun,
- DefaultBlockHook,
- RunputEof
- },
- };
-
- static int bg_color[3] = { 0, 0, 0 };
-
- rle_hdr rle_dflt_hdr = {
- RUN_DISPATCH, /* dispatch value */
- 3, /* 3 colors */
- bg_color, /* background color */
- 0, /* (alpha) if 1, save alpha channel */
- 2, /* (background) 0->just save pixels, */
- /* 1->overlay, 2->clear to bg first */
- 0, 511, /* (xmin, xmax) X bounds to save */
- 0, 511, /* (ymin, ymax) Y bounds to save */
- 0, /* ncmap (if != 0, save color map) */
- 8, /* cmaplen (log2 of length of color map) */
- NULL, /* pointer to color map */
- NULL, /* pointer to comment strings */
- stdout, /* output file */
- { 7 } /* RGB channels only */
- /* Can't initialize the union */
- };
- /*
- * This software is copyrighted as noted below. It may be freely copied,
- * modified, and redistributed, provided that the copyright notice is
- * preserved on all copies.
- *
- * There is no warranty or other guarantee of fitness for this software,
- * it is provided solely "as is". Bug reports or fixes may be sent
- * to the author, who may or may not act on them as he desires.
- *
- * You may not include this software in a program or other software product
- * without supplying the source, or without informing the end-user that the
- * source is available for no extra charge.
- *
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
- *
- * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
- * to have all "void" functions so declared.
- */
- /*
- * Runput.c - General purpose Run Length Encoding.
- *
- * Author: Spencer W. Thomas
- * Computer Science Dept.
- * University of Utah
- * Date: Mon Aug 9 1982
- * Copyright (c) 1982,1986 Spencer W. Thomas
- *
- * $Id: Runput.c,v 3.0 90/08/03 15:19:58 spencer Exp $
- *
- * Modified by: Todd W. Fuqua
- * Date: Jul 22 1984
- * convert to new RLE format to make room for larger frame buffers
- */
-
- /* THIS IS WAY OUT OF DATE. See rle.5.
- * The output file format is:
- *
- * Word 0: A "magic" number. The top byte of the word contains
- * the letter 'R' or the letter 'W'. 'W' indicates that
- * only black and white information was saved. The bottom
- * byte is one of the following:
- * ' ': Means a straight "box" save, -S flag was given.
- * 'B': Image saved with background color, clear screen to
- * background before restoring image.
- * 'O': Image saved in overlay mode.
- *
- * Words 1-6: The structure
- * { short xpos, Lower left corner
- * ypos,
- * xsize, Size of saved box
- * ysize;
- * char rgb[3]; Background color
- * char map; flag for map presence
- * }
- *
- * If the map flag is non-zero, then the color map will follow as
- * 3*256 16 bit words, first the red map, then the green map, and
- * finally the blue map.
- *
- * Following the setup information is the Run Length Encoded image.
- * Each instruction consists of a 4-bit opcode, a 12-bit datum and
- * possibly one or more following words (all words are 16 bits). The
- * instruction opcodes are:
- *
- * SkipLines (1): The bottom 10 bits are an unsigned number to be added to
- * current Y position.
- *
- * SetColor (2): The datum indicates which color is to be loaded with
- * the data described by the following ByteData and
- * RunData instructions. 0->red, 1->green, 2->blue. The
- * operation also resets the X position to the initial
- * X (i.e. a carriage return operation is performed).
- *
- * SkipPixels (3): The bottom 10 bits are an unsigned number to be
- * added to the current X position.
- *
- * ByteData (5): The datum is one less than the number of bytes of
- * color data following. If the number of bytes is
- * odd, a filler byte will be appended to the end of
- * the byte string to make an integral number of 16-bit
- * words. The bytes are in PDP-11 order. The X
- * position is incremented to follow the last byte of
- * data.
- *
- * RunData (6): The datum is one less than the run length. The
- * following word contains (in its lower 8 bits) the
- * color of the run. The X position is incremented to
- * follow the last byte in the run.
- */
-
- #include "stdio.h"
- #include "rle_code.h"
- #ifdef USE_STDLIB_H
- #include <stdlib.h>
- #include <malloc.h>
- #else
-
- #ifdef USE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif /* USE_STRING_H */
-
- #endif /* USE_STDLIB_H */
-
- #define UPPER 255 /* anything bigger ain't a byte */
-
- /*
- * Macros to make writing instructions with correct byte order easier.
- */
- /* Write a two-byte value in little_endian order. */
- #define put16(a) (putc((a)&0xff,rle_fd),putc(((a)>>8)&0xff,rle_fd))
-
- /* short instructions */
- #define mk_short_1(oper,a1) /* one argument short */ \
- putc(oper,rle_fd), putc((char)a1,rle_fd)
-
- #define mk_short_2(oper,a1,a2) /* two argument short */ \
- putc(oper,rle_fd), putc((char)a1,rle_fd), put16(a2)
-
- /* long instructions */
- #define mk_long_1(oper,a1) /* one argument long */ \
- putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), put16(a1)
-
- #define mk_long_2(oper,a1,a2) /* two argument long */ \
- putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), \
- put16(a1), put16(a2)
-
- /* choose between long and short format instructions */
- /* NOTE: these macros can only be used where a STATEMENT is legal */
-
- #define mk_inst_1(oper,a1) /* one argument inst */ \
- if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1))
-
- #define mk_inst_2(oper,a1,a2) /* two argument inst */ \
- if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2))
-
- /*
- * Opcode definitions
- */
- #define RSkipLines(n) mk_inst_1(RSkipLinesOp,(n))
-
- #define RSetColor(c) mk_short_1(RSetColorOp,(c))
- /* has side effect of performing */
- /* "carriage return" action */
-
- #define RSkipPixels(n) mk_inst_1(RSkipPixelsOp,(n))
-
- #define RNewLine RSkipLines(1)
-
- #define RByteData(n) mk_inst_1(RByteDataOp,n)
- /* followed by ((n+1)/2)*2 bytes */
- /* of data. If n is odd, last */
- /* byte will be ignored */
- /* "cursor" is left at pixel */
- /* following last pixel written */
-
- #define RRunData(n,c) mk_inst_2(RRunDataOp,(n),(c))
- /* next word contains color data */
- /* "cursor" is left at pixel after */
- /* end of run */
-
- #define REOF mk_inst_1(REOFOp,0)
- /* Really opcode only */
-
- extern char *vax_pshort();
-
- /*****************************************************************
- * TAG( RunSetup )
- * Put out initial setup data for RLE files.
- */
- int RunSetup(the_hdr)
- register rle_hdr * the_hdr;
- {
- struct XtndRsetup setup;
- register FILE * rle_fd = the_hdr->rle_file;
-
- put16( RLE_MAGIC );
-
- if ( the_hdr->background == 2 )
- setup.h_flags = H_CLEARFIRST;
- else if ( the_hdr->background == 0 )
- setup.h_flags = H_NO_BACKGROUND;
- else
- setup.h_flags = 0;
- if ( the_hdr->alpha )
- setup.h_flags |= H_ALPHA;
- if ( the_hdr->comments != NULL && *the_hdr->comments != NULL )
- setup.h_flags |= H_COMMENT;
-
- setup.h_ncolors = the_hdr->ncolors;
- setup.h_pixelbits = 8; /* Grinnell dependent */
- if ( the_hdr->ncmap > 0 && the_hdr->cmap == NULL )
- {
- fprintf( stderr,
- "Color map of size %d*%d specified, but not supplied\n" );
- the_hdr->ncmap = 0;
- }
- setup.h_cmaplen = the_hdr->cmaplen; /* log2 of color map size */
- setup.h_ncmap = the_hdr->ncmap; /* no of color channels */
- vax_pshort(setup.hc_xpos,the_hdr->xmin);
- vax_pshort(setup.hc_ypos,the_hdr->ymin);
- vax_pshort(setup.hc_xlen,the_hdr->xmax - the_hdr->xmin + 1);
- vax_pshort(setup.hc_ylen,the_hdr->ymax - the_hdr->ymin + 1);
- fwrite((char *)&setup, SETUPSIZE, 1, rle_fd);
- if ( the_hdr->background != 0 )
- {
- register int i;
- register rle_pixel *background =
- (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) );
- register int *bg_color;
- /*
- * If even number of bg color bytes, put out one more to get to
- * 16 bit boundary.
- */
- bg_color = the_hdr->bg_color;
- for ( i = 0; i < the_hdr->ncolors; i++ )
- background[i] = *bg_color++;
- /* Extra byte, if written, should be 0. */
- background[i] = 0;
- fwrite((char *)background, (the_hdr->ncolors / 2) * 2 + 1, 1, rle_fd);
- free( background );
- }
- else
- putc( '\0', rle_fd );
- if (the_hdr->ncmap > 0)
- {
- /* Big-endian machines are harder */
- register int i, nmap = (1 << the_hdr->cmaplen) *
- the_hdr->ncmap;
- register char *h_cmap = (char *)malloc( nmap * 2 );
- if ( h_cmap == NULL )
- {
- fprintf( stderr, "Malloc failed for color map of size %d\n",
- nmap );
- exit( 1 );
- }
- for ( i = 0; i < nmap; i++ )
- vax_pshort( &h_cmap[i*2], the_hdr->cmap[i] );
-
- fwrite( h_cmap, nmap, 2, rle_fd );
- free( h_cmap );
- }
-
- /* Now write out comments if given */
- if ( setup.h_flags & H_COMMENT )
- {
- int comlen;
- register CONST_DECL char ** com_p;
-
- /* Get the total length of comments */
- comlen = 0;
- for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
- comlen += 1 + strlen( *com_p );
-
- put16( comlen );
- for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
- fwrite( *com_p, 1, strlen( *com_p ) + 1, rle_fd );
-
- if ( comlen & 1 ) /* if odd length, round up */
- putc( '\0', rle_fd );
- }
- }
-
- /*****************************************************************
- * TAG( RunSkipBlankLines )
- * Skip one or more blank lines in the RLE file.
- */
- int RunSkipBlankLines(nblank, the_hdr)
- int nblank;
- register rle_hdr * the_hdr;
- {
- register FILE * rle_fd = the_hdr->rle_file;
- RSkipLines(nblank);
- }
-
- /*****************************************************************
- * TAG( RunSetColor )
- * Select a color and do carriage return.
- * color: 0 = Red, 1 = Green, 2 = Blue.
- */
- int RunSetColor(c, the_hdr)
- int c;
- register rle_hdr * the_hdr;
- {
- register FILE * rle_fd = the_hdr->rle_file;
- RSetColor(c);
- }
-
- /*****************************************************************
- * TAG( RunSkipPixels )
- * Skip a run of background.
- */
-
- /* ARGSUSED */
- int RunSkipPixels(nskip, last, wasrun, the_hdr)
- int nskip, last, wasrun;
- register rle_hdr * the_hdr;
- {
- register FILE * rle_fd = the_hdr->rle_file;
- if (! last && nskip > 0)
- {
- RSkipPixels(nskip);
- }
- }
-
- /*****************************************************************
- * TAG( RunNewScanLine )
- * Perform a newline action. Since CR is implied by the Set Color
- * operation, only generate code if the newline flag is true.
- */
- int RunNewScanLine (int flag, register rle_hdr *the_hdr)
- /*
- int RunNewScanLine(flag, the_hdr)
- int flag;
- register rle_hdr * the_hdr;
- */
- {
- register FILE * rle_fd = the_hdr->rle_file;
- if (flag)
- {
- RNewLine;
- }
- }
-
- /*****************************************************************
- * TAG( Runputdata )
- * Put one or more pixels of byte data into the output file.
- */
- int Runputdata(buf, n, the_hdr)
- rle_pixel * buf;
- int n;
- register rle_hdr * the_hdr;
- {
- register FILE * rle_fd = the_hdr->rle_file;
- if (n == 0)
- return;
-
- RByteData(n-1);
- fwrite((char *)buf, n, 1, rle_fd);
- if ( n & 1 )
- putc( 0, rle_fd );
- }
-
- /*****************************************************************
- * TAG( Runputrun )
- * Output a single color run.
- */
-
- /* ARGSUSED */
- int Runputrun(color, n, last, the_hdr)
- int color, n, last;
- register rle_hdr * the_hdr;
- {
- register FILE * rle_fd = the_hdr->rle_file;
- RRunData(n-1,color);
- }
-
-
- /*****************************************************************
- * TAG( RunputEof )
- * Output an EOF opcode
- */
- int RunputEof( the_hdr )
- register rle_hdr * the_hdr;
- {
- register FILE * rle_fd = the_hdr->rle_file;
- REOF;
- }
- /*
- * V A X S H O R T
- *
- * Code to manipulate 16-bit integers in VAX order in a
- * machine independent manner.
- *
- * (VAX is a trademark of Digital Equipment Corporation)
- *
- * Author -
- * Michael John Muuss
- *
- * Source -
- * SECAD/VLD Computing Consortium, Bldg 394
- * The U. S. Army Ballistic Research Laboratory
- * Aberdeen Proving Ground, Maryland 21005-5066
- *
- * Distribution Status -
- * Public Domain, Distribution Unlimitied.
- */
- #ifndef lint
- static char RCSid[] = "@(#)$Id: vaxshort.c,v 3.0 90/08/03 15:21:30 spencer Exp $ (BRL)";
- #endif
-
- /*
- * V A X _ P S H O R T
- */
- char *vax_pshort(msgp, s)
- register char *msgp;
- register unsigned short s;
- {
-
- msgp[0] = s & 0xFF;
- msgp[1] = s >> 8;
- return(msgp+2);
- }
-