jimf@saber.com (09/28/90)
Submitted-by: saber.com!jimf@saber.com Posting-number: Volume 9, Issue 54 Archive-name: xloadimage/part07 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 7 (of 9)." # Contents: rlelib.c # Wrapped by jimf@armory on Tue Sep 25 19:37:42 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'rlelib.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rlelib.c'\" else echo shar: Extracting \"'rlelib.c'\" \(50248 characters\) sed "s/^X//" >'rlelib.c' <<'END_OF_FILE' X/* X * Utah RLE Toolkit library routines. X * X * Read image support only. X * X * Cobbled from Utah RLE include and library source files. X * X * By Graeme Gill X * 30/5/90 X * X */ X X#include <stdio.h> X#include <math.h> X#include <varargs.h> X#include <ctype.h> X X#include "image.h" /* need ZFILE definition */ X#include "rle.h" X X#define zeof(zfp) feof((zfp)->stream) X X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X */ X/* X * Runsv.h - Definitions for Run Length Encoding. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Mon Aug 9 1982 X * Copyright (c) 1982 Spencer W. Thomas X * X * $Header: XtndRunsv.h,v 2.2 85/04/26 15:05:30 thomas Exp $ X */ X X#ifndef XTNDRUNSV X#define XTNDRUNSV X X/* X * Opcode definitions X */ X X#define LONG 0x40 X#define RSkipLinesOp 1 X#define RSetColorOp 2 X#define RSkipPixelsOp 3 X#define RByteDataOp 5 X#define RRunDataOp 6 X#define REOFOp 7 X X#define H_CLEARFIRST 0x1 /* clear framebuffer flag */ X#define H_NO_BACKGROUND 0x2 /* if set, no bg color supplied */ X#define H_ALPHA 0x4 /* if set, alpha channel (-1) present */ X#define H_COMMENT 0x8 /* if set, comments present */ X Xstruct XtndRsetup X{ X short h_xpos, X h_ypos, X h_xlen, X h_ylen; X char h_flags, X h_ncolors, X h_pixelbits, X h_ncmap, X h_cmaplen; X}; X#define SETUPSIZE ((4*2)+5) X X/* "Old" RLE format magic numbers */ X#define RMAGIC ('R' << 8) /* top half of magic number */ X#define WMAGIC ('W' << 8) /* black&white rle image */ X X#define XtndRMAGIC ((short)0xcc52) /* RLE file magic number */ X X#endif /* XTNDRUNSV */ X X/* "svfb.h" */ X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X */ X/* X * svfb.h - Definitions and a few global variables for svfb. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Mon Aug 9 1982 X * Copyright (c) 1982 Spencer W. Thomas X * X * $Header: svfb.h,v 2.4 86/02/27 10:03:26 thomas Exp $ X */ X X/* **************************************************************** X * Dispatch table for different output types. X */ Xtypedef void sv_fn(); Xstruct sv_dispatch_tab { X char *magic; /* magic type flags */ X sv_fn *setup, /* startup function */ X *skipBlankLines, X *setColor, X *skipPixels, X *newScanLine, X *putdat, /* put a set of differing pixels */ X *putrn, /* put a run all the same */ X *blockHook, /* hook called at start of new */ X /* output block */ X *putEof; /* write EOF marker (if possible) */ X}; X Xstruct sv_dispatch_tab sv_DTable[]; X X/* X * These definitions presume the existence of a variable called X * "fileptr", declared "long * fileptr". *fileptr should be X * initialized to 0 before calling Setup(). X * A pointer "globals" declared "struct sv_globals * globals" is also X * presumed to exist. X */ X#define sv_magic (sv_DTable[(int)globals->sv_dispatch].magic) X#define Setup() (*sv_DTable[(int)globals->sv_dispatch].setup)(globals) X#define SkipBlankLines(n) (*sv_DTable[(int)globals->sv_dispatch].skipBlankLines)(n, globals) X#define SetColor(c) (*sv_DTable[(int)globals->sv_dispatch].setColor)(c, globals) X#define SkipPixels(n, l, r) (*sv_DTable[(int)globals->sv_dispatch].skipPixels)(n,l,r, globals) X#define NewScanLine(flag) (*sv_DTable[(int)globals->sv_dispatch].newScanLine)(flag, globals) X#define putdata(buf, len) (*sv_DTable[(int)globals->sv_dispatch].putdat)(buf, len, globals) X#define putrun(val, len, f) (*sv_DTable[(int)globals->sv_dispatch].putrn)(val,len,f, globals) X#define BlockHook() (*sv_DTable[(int)globals->sv_dispatch].blockHook)(globals) X#define PutEof() (*sv_DTable[(int)globals->sv_dispatch].putEof)(globals) X X/* X * States for run detection X */ X#define DATA 0 X#define RUN2 1 X#define RUN3 2 X#define RUN4 3 X#define INRUN -1 X X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire X * to have all "void" functions so declared. X */ X/* X * svfb_global.c - Global variable initialization for svfb routines. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Thu Apr 25 1985 X * Copyright (c) 1985,1986 Spencer W. Thomas X * X * $Header: svfb_global.c,v 2.6 86/02/27 10:05:23 thomas Exp $ X * $Log: svfb_global.c,v $ X * Revision 2.6 86/02/27 10:05:23 thomas X * Change for new sv_globals X * X * Revision 2.5 86/02/25 17:32:18 thomas X * Take out misc.h X * X * Revision 2.4 85/04/26 15:09:27 thomas X * Add header comment. Change DTable to sv_DTable. Changes for new X * sv_globals structure. X * X */ X X Xvoid RunSetup(), X RunSkipBlankLines(), X RunSetColor(), X RunSkipPixels(), X RunNewScanLine(), X Runputdata(), X Runputrun(), X RunputEof(); X Xvoid DefaultBlockHook(); Xvoid NullputEof(); X Xstruct sv_dispatch_tab sv_DTable[] = { X { X " OB", X RunSetup, X RunSkipBlankLines, X RunSetColor, X RunSkipPixels, X RunNewScanLine, X Runputdata, X Runputrun, X DefaultBlockHook, X RunputEof X }, X}; X Xstatic int sv_bg_color[3] = { 0, 0, 0 }; X Xstruct sv_globals sv_globals = { X RUN_DISPATCH, /* dispatch value */ X 3, /* 3 colors */ X sv_bg_color, /* background color */ X 0, /* (alpha) if 1, save alpha channel */ X 2, /* (background) 0->just save pixels, */ X /* 1->overlay, 2->clear to bg first */ X 0, 511, /* (xmin, xmax) X bounds to save */ X 0, 479, /* (ymin, ymax) Y bounds to save */ X 0, /* ncmap (if != 0, save color map) */ X 8, /* cmaplen (log2 of length of color map) */ X NULL, /* pointer to color map */ X NULL, /* pointer to comment strings */ X NULL, /* output file */ X { 7 } /* RGB channels only */ X /* Can't initialize the union */ X}; X X/* ARGSUSED */ Xvoid XNullputEof(globals) Xstruct sv_globals * globals; X{ X /* do nothing */ X} X X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire X * to have all "void" functions so declared. X */ X/* X * Runsv.c - General purpose Run Length Encoding for svfb. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Mon Aug 9 1982 X * Copyright (c) 1982,1986 Spencer W. Thomas X * X * $Header: Runsv.c,v 2.9 86/02/27 10:01:13 thomas Locked $ X * X * Modified by: Todd W. Fuqua X * Date: Jul 22 1984 X * convert to new RLE format to make room for larger frame buffers X */ X X/* THIS IS WAY OUT OF DATE. See rle.5. X * The output file format is: X * X * Word 0: A "magic" number. The top byte of the word contains X * the letter 'R' or the letter 'W'. 'W' indicates that X * only black and white information was saved. The bottom X * byte is one of the following: X * ' ': Means a straight "box" save, -S flag was given. X * 'B': Image saved with background color, clear screen to X * background before restoring image. X * 'O': Image saved in overlay mode. X * X * Words 1-6: The structure X * { * short xpos, /* Lower left corner X * ypos, X * xsize, /* Size of saved box X * ysize; X * char rgb[3]; /* Background color X * char map; /* flag for map presence X * } X * X * If the map flag is non-zero, then the color map will follow as X * 3*256 16 bit words, first the red map, then the green map, and X * finally the blue map. X * X * Following the setup information is the Run Length Encoded image. X * Each instruction consists of a 4-bit opcode, a 12-bit datum and X * possibly one or more following words (all words are 16 bits). The X * instruction opcodes are: X * X * SkipLines (1): The bottom 10 bits are an unsigned number to be added to X * current Y position. X * X * SetColor (2): The datum indicates which color is to be loaded with X * the data described by the following ByteData and X * RunData instructions. 0->red, 1->green, 2->blue. The X * operation also resets the X position to the initial X * X (i.e. a carriage return operation is performed). X * X * SkipPixels (3): The bottom 10 bits are an unsigned number to be X * added to the current X position. X * X * ByteData (5): The datum is one less than the number of bytes of X * color data following. If the number of bytes is X * odd, a filler byte will be appended to the end of X * the byte string to make an integral number of 16-bit X * words. The bytes are in PDP-11 order. The X X * position is incremented to follow the last byte of X * data. X * X * RunData (6): The datum is one less than the run length. The X * following word contains (in its lower 8 bits) the X * color of the run. The X position is incremented to X * follow the last byte in the run. X */ X X#define UPPER 255 /* anything bigger ain't a byte */ X X/* Predefine LITTLE_ENDIAN for vax and pdp11 machines */ X#if defined(vax) || defined(pdp11) X#define LITTLE_ENDIAN X#endif X X#ifndef LITTLE_ENDIAN Xstatic rle_pixel t; Xstatic rle_pixel *a1,*a2; Xstatic short tm; X#endif X X#ifdef LITTLE_ENDIAN X#define ASN(a,b) a = b X#else X#define ASN(a,b) (tm=(int)(b)),(a1=(rle_pixel*)(&(a))),\ X (a2=(rle_pixel*)(&(tm))),(*a1=(*(a2+1))),(*(a1+1)=(*a2)) X#endif X X/* X * Macros to make writing instructions with correct byte order easier. X */ Xunion { short s; char c[2]; } arg; X#ifdef LITTLE_ENDIAN X#define put16(a) arg.s=a,putc(arg.c[0],sv_fd), putc(arg.c[1],sv_fd) X#else X#define put16(a) arg.s=a,putc(arg.c[1],sv_fd), putc(arg.c[0],sv_fd) X#endif X X/* short instructions */ X#define mk_short_1(oper,a1) /* one argument short */ \ X putc(oper,sv_fd), putc((char)a1,sv_fd) X X#define mk_short_2(oper,a1,a2) /* two argument short */ \ X putc(oper,sv_fd), putc((char)a1,sv_fd), put16(a2) X X/* long instructions */ X#define mk_long_1(oper,a1) /* one argument long */ \ X putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), put16(a1) X X#define mk_long_2(oper,a1,a2) /* two argument long */ \ X putc((char)(LONG|oper),sv_fd), putc('\0', sv_fd), \ X put16(a1), put16(a2) X X/* choose between long and short format instructions */ X/* NOTE: these macros can only be used where a STATEMENT is legal */ X X#define mk_inst_1(oper,a1) /* one argument inst */ \ X if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1)) X X#define mk_inst_2(oper,a1,a2) /* two argument inst */ \ X if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2)) X X/* X * Opcode definitions X */ X#define RSkipLines(n) mk_inst_1(RSkipLinesOp,(n)) X X#define RSetColor(c) mk_short_1(RSetColorOp,(c)) X /* has side effect of performing */ X /* "carriage return" action */ X X#define RSkipPixels(n) mk_inst_1(RSkipPixelsOp,(n)) X X#define RNewLine RSkipLines(1) X X#define RByteData(n) mk_inst_1(RByteDataOp,n) X /* followed by ((n+1)/2)*2 bytes */ X /* of data. If n is odd, last */ X /* byte will be ignored */ X /* "cursor" is left at pixel */ X /* following last pixel written */ X X#define RRunData(n,c) mk_inst_2(RRunDataOp,(n),(c)) X /* next word contains color data */ X /* "cursor" is left at pixel after */ X /* end of run */ X X#define REOF mk_inst_1(REOFOp,0) X /* Really opcode only */ X X/***************************************************************** X * TAG( RunSetup ) X * Put out initial setup data for RLE svfb files. X */ Xvoid XRunSetup(globals) Xregister struct sv_globals * globals; X{ X} X X/***************************************************************** X * TAG( RunSkipBlankLines ) X * Skip one or more blank lines in the RLE file. X */ Xvoid XRunSkipBlankLines(nblank, globals) Xregister struct sv_globals * globals; X{ X} X X/***************************************************************** X * TAG( RunSetColor ) X * Select a color and do carriage return. X * color: 0 = Red, 1 = Green, 2 = Blue. X */ Xvoid XRunSetColor(c, globals) Xregister struct sv_globals * globals; X{ X} X X/***************************************************************** X * TAG( RunSkipPixels ) X * Skip a run of background. X */ X X/* ARGSUSED */ Xvoid XRunSkipPixels(nskip, last, wasrun, globals) Xregister struct sv_globals * globals; X{ X} X X/***************************************************************** X * TAG( RunNewScanLine ) X * Perform a newline action. Since CR is implied by the Set Color X * operation, only generate code if the newline flag is true. X */ Xvoid XRunNewScanLine(flag, globals) Xregister struct sv_globals * globals; X{ X} X X/***************************************************************** X * TAG( Runputdata ) X * Put one or more pixels of byte data into the output file. X */ Xvoid XRunputdata(buf, n, globals) Xrle_pixel * buf; Xregister struct sv_globals * globals; X{ X} X X/***************************************************************** X * TAG( Runputrun ) X * Output a single color run. X */ X X/* ARGSUSED */ Xvoid XRunputrun(color, n, last, globals) Xregister struct sv_globals * globals; X{ X} X X X/***************************************************************** X * TAG( RunputEof ) X * Output an EOF opcode X */ Xvoid XRunputEof( globals ) Xregister struct sv_globals * globals; X{ X} X X/*ARGSUSED*/ Xvoid XDefaultBlockHook(globals) Xstruct sv_globals * globals; X{ X} X X X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X */ X/* X * buildmap.c - Build a color map from the RLE file color map. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Sat Jan 24 1987 X * Copyright (c) 1987, University of Utah X */ X X/***************************************************************** X * TAG( buildmap ) X * X * Returns a color map that can easily be used to map the pixel values in X * an RLE file. Map is built from the color map in the input file. X * Inputs: X * globals: sv_globals structure containing color map. X * minmap: Minimum number of channels in output map. X * gamma: Adjust color map for this image gamma value X * (1.0 means no adjustment). X * Outputs: X * Returns an array of pointers to arrays of rle_pixels. The array X * of pointers contains max(sv_ncolors, sv_ncmap) elements, each X * array of pixels contains 2^sv_cmaplen elements. The pixel arrays X * should be considered read-only. X * Assumptions: X * [None] X * Algorithm: X * Ensure that there are at least sv_ncolors rows in the map, and X * that each has at least 256 elements in it (largest map that can X * be addressed by an rle_pixel). X */ Xrle_pixel ** Xbuildmap( globals, minmap, gamma ) Xstruct sv_globals *globals; Xint minmap; Xdouble gamma; X{ X rle_pixel ** cmap, * gammap; X register int i, j; X int maplen, cmaplen, ncmap, nmap; X X if ( globals->sv_ncmap == 0 ) /* make identity map */ X { X nmap = (minmap < globals->sv_ncolors) ? globals->sv_ncolors : minmap; X cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); X cmap[0] = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) ); X for ( i = 0; i < 256; i++ ) X cmap[0][i] = i; X for ( i = 1; i < nmap; i++ ) X cmap[i] = cmap[0]; X maplen = 256; X ncmap = 1; /* number of unique rows */ X } X else /* make map from globals */ X { X /* Map is at least 256 long */ X cmaplen = (1 << globals->sv_cmaplen); X if ( cmaplen < 256 ) X maplen = 256; X else X maplen = cmaplen; X X if ( globals->sv_ncmap == 1 ) /* make "b&w" map */ X { X nmap = (minmap < globals->sv_ncolors) ? X globals->sv_ncolors : minmap; X cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); X cmap[0] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) ); X for ( i = 0; i < maplen; i++ ) X if ( i < cmaplen ) X cmap[0][i] = globals->sv_cmap[i] >> 8; X else X cmap[0][i] = i; X for ( i = 1; i < nmap; i++ ) X cmap[i] = cmap[0]; X ncmap = 1; X } X else if ( globals->sv_ncolors <= globals->sv_ncmap ) X { X nmap = (minmap < globals->sv_ncmap) ? globals->sv_ncmap : minmap; X cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); X for ( j = 0; j < globals->sv_ncmap; j++ ) X { X cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) ); X for ( i = 0; i < maplen; i++ ) X if ( i < cmaplen ) X cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8; X else X cmap[j][i] = i; X } X for ( i = j, j--; i < nmap; i++ ) X cmap[i] = cmap[j]; X ncmap = globals->sv_ncmap; X } X else /* ncolors > ncmap */ X { X nmap = (minmap < globals->sv_ncolors) ? X globals->sv_ncolors : minmap; X cmap = (rle_pixel **)lmalloc( nmap * sizeof(rle_pixel *) ); X for ( j = 0; j < globals->sv_ncmap; j++ ) X { X cmap[j] = (rle_pixel *)lmalloc( maplen * sizeof(rle_pixel) ); X for ( i = 0; i < maplen; i++ ) X if ( i < cmaplen ) X cmap[j][i] = globals->sv_cmap[j*cmaplen + i] >> 8; X else X cmap[j][i] = i; X } X for( i = j, j--; i < nmap; i++ ) X cmap[i] = cmap[j]; X ncmap = globals->sv_ncmap; X } X } X X /* Gamma compensate if requested */ X if ( gamma != 1.0 ) X { X gammap = (rle_pixel *)lmalloc( 256 * sizeof(rle_pixel) ); X for ( i = 0; i < 256; i++ ) X { X#ifdef BYTEBUG X int byteb1; X byteb1 = (int)(0.5 + 255.0 * pow( i / 255.0, gamma )); X gammap[i] = byteb1; X#else X gammap[i] = (int)(0.5 + 255.0 * pow( i / 255.0, gamma )); X#endif X } X for ( i = 0; i < ncmap; i++ ) X for ( j = 0; j < maplen; j++ ) X cmap[i][j] = gammap[cmap[i][j]]; X } X X return cmap; X} X X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X */ X/* X * rle_getcom.c - Get specific comments from globals structure. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Sun Jan 25 1987 X * Copyright (c) 1987, University of Utah X */ X X/***************************************************************** X * TAG( match ) X * X * Match a name against a test string for "name=value" or "name". X * If it matches name=value, return pointer to value part, if just X * name, return pointer to NUL at end of string. If no match, return NULL. X * X * Inputs: X * n: Name to match. May also be "name=value" to make it easier X * to replace comments. X * v: Test string. X * Outputs: X * Returns pointer as above. X * Assumptions: X * [None] X * Algorithm: X * [None] X */ Xstatic char * Xmatch( n, v ) Xregister char *n; Xregister char *v; X{ X for ( ; *n != '\0' && *n != '=' && *n == *v; n++, v++ ) X ; X if (*n == '\0' || *n == '=') X if ( *v == '\0' ) X return v; X else if ( *v == '=' ) X return ++v; X X return NULL; X} X X/***************************************************************** X * TAG( rle_getcom ) X * X * Return a pointer to the value part of a name=value pair in the comments. X * Inputs: X * name: Name part of the comment to search for. X * globals: sv_globals structure. X * Outputs: X * Returns pointer to value part of comment or NULL if no match. X * Assumptions: X * [None] X * Algorithm: X * [None] X */ Xchar * Xrle_getcom( name, globals ) Xchar *name; Xstruct sv_globals *globals; X{ X char ** cp; X char * v; X X if ( globals->sv_comments == NULL ) X return NULL; X X for ( cp = globals->sv_comments; *cp; cp++ ) X if ( (v = match( name, *cp )) != NULL ) X return v; X X return NULL; X} X X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire X * to have all "void" functions so declared. X */ X/* X * rle_getrow.c - Read an RLE file in. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Wed Apr 10 1985 X * Copyright (c) 1985 Spencer W. Thomas X * X * $Header: rle_getrow.c,v 1.12 86/11/10 12:30:34 thomas Exp $ X * $Log: rle_getrow.c,v $ X * Revision 1.12 86/11/10 12:30:34 thomas X * NULL comments field if no comment in input file. X * X * Revision 1.11 86/11/10 11:27:01 thomas X * Remove infile arguments. X * X * Revision 1.10 86/11/10 11:19:04 thomas X * Fix to work with pipe input. X * X * Revision 1.9 86/10/08 13:06:32 thomas X * Add header comments. X * Add EOF opcode. X * X * Revision 1.6 86/02/27 10:05:55 thomas X * Change for new sv_globals interface. Put "static" vars in structure. X * X * Revision 1.5 86/02/25 17:32:28 thomas X * Add debugging. X * X * Revision 1.4 86/02/11 11:38:09 thomas X * Oops: Only did clear to background right for ncolors = 3. X * Some lint fixes. X * X * Revision 1.3 86/02/11 11:27:52 thomas X * Handle alpha channel. Use bfill routine for efficiency. X * X * Revision 1.2 85/05/22 15:09:23 thomas X * Swap magic number on BIGENDIAN machines. X * X * Revision 1.1 85/05/22 12:36:21 thomas X * Initial revision X * X */ X/* X * Automatically define LITTLE_ENDIAN on vax and pdp11 machines X */ X#if defined(vax) || defined(pdp11) X#define LITTLE_ENDIAN X#endif X Xstruct inst { X unsigned opcode:8, datum:8; X}; X X#define BREAD(type, var, len)\ X zread( infile, (char *)&var,len ) X#define OPCODE(inst) (inst.opcode & ~LONG) X#define LONGP(inst) (inst.opcode & LONG) X#define DATUM(inst) (0x00ff & inst.datum) X Xstatic int debug_f; /* if non-zero, print debug info */ Xstatic void bfill(); X X/***************************************************************** X * TAG( rle_get_setup ) X * X * Read the initialization information from an RLE file. X * Inputs: X * globals: Contains pointer to the input file. X * Outputs: X * globals: Initialized with information from the X * input file. X * Returns 0 on success, -1 if the file is not an RLE file, X * -2 if malloc of the color map failed, -3 if an immediate EOF X * is hit (empty input file), and -4 if an EOF is encountered reading X * the setup information. X * Assumptions: X * infile points to the "magic" number in an RLE file (usually X * byte 0 in the file). X * Algorithm: X * Read in the setup info and fill in sv_globals. X */ Xrle_get_setup( globals ) Xstruct sv_globals * globals; X{ X struct XtndRsetup setup; X short magic; /* assume 16 bits */ X register ZFILE *infile = globals->svfb_fd; X rle_pixel * bg_color; X register int i; X char * comment_buf; X X BREAD( short, magic, sizeof magic ); X SWAB(magic); X if ( zeof( infile ) ) X return -3; X if ( magic != XtndRMAGIC ) X return -1; X BREAD( struct XtndRsetup, setup, SETUPSIZE ); /* assume VAX packing */ X if ( zeof( infile ) ) X return -4; X SWAB( setup.h_xpos ); X SWAB( setup.h_ypos ); X SWAB( setup.h_xlen ); X SWAB( setup.h_ylen ); X X /* Extract information from setup */ X globals->sv_ncolors = setup.h_ncolors; X for ( i = 0; i < globals->sv_ncolors; i++ ) X SV_SET_BIT( *globals, i ); X X if ( !(setup.h_flags & H_NO_BACKGROUND) ) X { X globals->sv_bg_color = (int *)lmalloc( X (unsigned)(sizeof(int) * setup.h_ncolors) ); X bg_color = (rle_pixel *)lmalloc( X (unsigned)(1 + (setup.h_ncolors / 2) * 2) ); X zread( infile, (char *)bg_color, 1 + (setup.h_ncolors / 2) * 2 ); X for ( i = 0; i < setup.h_ncolors; i++ ) X globals->sv_bg_color[i] = bg_color[i]; X lfree( bg_color ); X } X else X zgetc( infile ); /* skip filler byte */ X X if ( setup.h_flags & H_NO_BACKGROUND ) X globals->sv_background = 0; X else if ( setup.h_flags & H_CLEARFIRST ) X globals->sv_background = 2; X else X globals->sv_background = 1; X if ( setup.h_flags & H_ALPHA ) X { X globals->sv_alpha = 1; X SV_SET_BIT( *globals, SV_ALPHA ); X } X else X globals->sv_alpha = 0; X X globals->sv_xmin = setup.h_xpos; X globals->sv_ymin = setup.h_ypos; X globals->sv_xmax = globals->sv_xmin + setup.h_xlen - 1; X globals->sv_ymax = globals->sv_ymin + setup.h_ylen - 1; X X globals->sv_ncmap = setup.h_ncmap; X globals->sv_cmaplen = setup.h_cmaplen; X if ( globals->sv_ncmap > 0 ) X { X register int maplen = X globals->sv_ncmap * (1 << globals->sv_cmaplen); X globals->sv_cmap = (rle_map *)lmalloc( X (unsigned)(sizeof(rle_map) * maplen) ); X if ( globals->sv_cmap == NULL ) X { X fprintf( stderr, X "Malloc failed for color map of size %d*%d in rle_get_setup\n", X globals->sv_ncmap, (1 << globals->sv_cmaplen) ); X return -2; X } X zread( infile, (char *)globals->sv_cmap, sizeof(short) * maplen ); X#ifndef LITTLE_ENDIAN X /* Swap bytes on bigendian machines X */ X for ( i = 0; i < maplen; i++ ) X SWAB( globals->sv_cmap[i] ); X#endif X } X X /* Check for comments */ X if ( setup.h_flags & H_COMMENT ) X { X short comlen, evenlen; X register char * cp; X X BREAD( short, comlen, sizeof comlen ); /* get comment length */ X SWAB( comlen ); X evenlen = (comlen + 1) & ~1; /* make it even */ X comment_buf = (char *)lmalloc( (unsigned) evenlen ); X if ( comment_buf == NULL ) X { X fprintf( stderr, X "Malloc failed for comment buffer of size %d in rle_get_setup\n", X comlen ); X return -2; X } X zread( infile, comment_buf, evenlen ); X /* Count the comments */ X for ( i = 0, cp = comment_buf; cp < comment_buf + comlen; cp++ ) X if ( *cp == 0 ) X i++; X i++; /* extra for NULL pointer at end */ X /* Get space to put pointers to comments */ X globals->sv_comments = X (char **)lmalloc( (unsigned)(i * sizeof(char *)) ); X if ( globals->sv_comments == NULL ) X { X fprintf( stderr, X "Malloc failed for %d comment pointers in rle_get_setup\n", X i ); X return -2; X } X /* Get pointers to the comments */ X *globals->sv_comments = comment_buf; X for ( i = 1, cp = comment_buf + 1; cp < comment_buf + comlen; cp++ ) X if ( *(cp - 1) == 0 ) X globals->sv_comments[i++] = cp; X globals->sv_comments[i] = NULL; X } X else X globals->sv_comments = NULL; X X /* Initialize state for rle_getrow */ X globals->sv_private.get.scan_y = globals->sv_ymin; X globals->sv_private.get.vert_skip = 0; X globals->sv_private.get.is_eof = 0; X globals->sv_private.get.is_seek = 0; /* Can't do seek on zfile */ X debug_f = 0; X X if ( !zeof( infile ) ) X return 0; /* success! */ X else X { X globals->sv_private.get.is_eof = 1; X return -4; X } X} X X X/***************************************************************** X * TAG( rle_get_error ) X * X * Print an error message for the return code from rle_get_setup X * Inputs: X * code: The return code from rle_get_setup. X * pgmname: Name of this program (argv[0]). X * fname: Name of the input file. X * Outputs: X * Prints an error message on standard output. X * Returns code. X */ X Xrle_get_error( code, pgmname, fname ) Xchar *pgmname; Xchar *fname; X{ X switch( code ) X { X case 0: /* success */ X break; X X case -1: /* Not an RLE file */ X fprintf( stderr, "%s: %s is not an RLE file\n", X pgmname, fname ); X break; X X case -2: /* malloc failed */ X fprintf( stderr, X "%s: Malloc failed reading header of file %s\n", X pgmname, fname ); X break; X X case -3: X fprintf( stderr, "%s: %s is an empty file\n", pgmname, fname ); X break; X X case -4: X fprintf( stderr, X "%s: RLE header of %s is incomplete (premature EOF)\n", X pgmname, fname ); X break; X X default: X fprintf( stderr, "%s: Error encountered reading header of %s\n", X pgmname, fname ); X break; X } X return code; X} X X X/***************************************************************** X * TAG( rle_get_setup_ok ) X * X * Read the initialization information from an RLE file. X * Inputs: X * globals: Contains pointer to the input file. X * prog_name: Program name to be printed in the error message. X * file_name: File name to be printed in the error message. X * If NULL, the string "stdin" is generated. X * Outputs: X * globals: Initialized with information from the X * input file. X * If reading the globals fails, it prints an error message X * and exits with the appropriate status code. X * Algorithm: X * sv_get_setup does all the work. X */ Xvoid Xrle_get_setup_ok( globals, prog_name, file_name ) Xstruct sv_globals * globals; Xchar *prog_name; Xchar *file_name; X{ X int code; X X if (! file_name) X file_name = "stdin"; X X code = rle_get_error( rle_get_setup( globals ), prog_name, file_name ); X if (code) X exit( code ); X} X X X/***************************************************************** X * TAG( rle_debug ) X * X * Turn RLE debugging on or off. X * Inputs: X * on_off: if 0, stop debugging, else start. X * Outputs: X * Sets internal debug flag. X * Assumptions: X * [None] X * Algorithm: X * [None] X */ Xvoid Xrle_debug( on_off ) Xint on_off; X{ X debug_f = on_off; X} X X X/***************************************************************** X * TAG( rle_getrow ) X * X * Get a scanline from the input file. X * Inputs: X * globals: sv_globals structure containing information about X * the input file. X * Outputs: X * scanline: an array of pointers to the individual color X * scanlines. Scanline is assumed to have X * globals->sv_ncolors pointers to arrays of rle_pixel, X * each of which is at least globals->sv_xmax+1 long. X * Returns the current scanline number. X * Assumptions: X * rle_get_setup has already been called. X * Algorithm: X * If a vertical skip is being executed, and clear-to-background is X * specified (globals->sv_background is true), just set the X * scanlines to the background color. If clear-to-background is X * not set, just increment the scanline number and return. X * X * Otherwise, read input until a vertical skip is encountered, X * decoding the instructions into scanline data. X */ X Xrle_getrow( globals, scanline ) Xstruct sv_globals * globals; Xrle_pixel *scanline[]; X{ X register rle_pixel * scanc; X register int nc; X register ZFILE *infile = globals->svfb_fd; X int scan_x = globals->sv_xmin, /* current X position */ X channel = 0; /* current color channel */ X short word, long_data; X struct inst inst; X X /* Clear to background if specified */ X if ( globals->sv_background == 2 ) X { X if ( globals->sv_alpha && SV_BIT( *globals, -1 ) ) X bfill( (char *)scanline[-1], globals->sv_xmax + 1, 0 ); X for ( nc = 0; nc < globals->sv_ncolors; nc++ ) X if ( SV_BIT( *globals, nc ) ) X bfill( (char *)scanline[nc], globals->sv_xmax+1, X globals->sv_bg_color[nc] ); X } X X /* If skipping, then just return */ X if ( globals->sv_private.get.vert_skip > 0 ) X { X globals->sv_private.get.vert_skip--; X globals->sv_private.get.scan_y++; X if ( globals->sv_private.get.vert_skip > 0 ) X return globals->sv_private.get.scan_y; X } X X /* If EOF has been encountered, return also */ X if ( globals->sv_private.get.is_eof ) X return ++globals->sv_private.get.scan_y; X X /* Otherwise, read and interpret instructions until a skipLines X * instruction is encountered. X */ X if ( SV_BIT( *globals, channel ) ) X scanc = scanline[channel] + scan_x; X else X scanc = NULL; X for (;;) X { X BREAD(struct inst, inst, 2 ); X if ( zeof(infile) ) X { X globals->sv_private.get.is_eof = 1; X break; /* <--- one of the exits */ X } X X switch( OPCODE(inst) ) X { X case RSkipLinesOp: X if ( LONGP(inst) ) X { X BREAD( short, long_data, sizeof long_data ); X SWAB( long_data ); X globals->sv_private.get.vert_skip = long_data; X } X else X globals->sv_private.get.vert_skip = DATUM(inst); X if (debug_f) X fprintf(stderr, "Skip %d Lines (to %d)\n", X globals->sv_private.get.vert_skip, X globals->sv_private.get.scan_y + X globals->sv_private.get.vert_skip ); X X break; /* need to break for() here, too */ X X case RSetColorOp: X channel = DATUM(inst); /* select color channel */ X if ( channel == 255 ) X channel = -1; X scan_x = globals->sv_xmin; X if ( SV_BIT( *globals, channel ) ) X scanc = scanline[channel]+scan_x; X if ( debug_f ) X fprintf( stderr, "Set color to %d (reset x to %d)\n", X channel, scan_x ); X break; X X case RSkipPixelsOp: X if ( LONGP(inst) ) X { X BREAD( short, long_data, sizeof long_data ); X SWAB( long_data ); X scan_x += long_data; X scanc += long_data; X if ( debug_f ) X fprintf( stderr, "Skip %d pixels (to %d)\n", X long_data, scan_x ); X X } X else X { X scan_x += DATUM(inst); X scanc += DATUM(inst); X if ( debug_f ) X fprintf( stderr, "Skip %d pixels (to %d)\n", X DATUM(inst), scan_x ); X } X break; X X case RByteDataOp: X if ( LONGP(inst) ) X { X BREAD( short, long_data, sizeof long_data ); X SWAB( long_data ); X nc = (int)long_data; X } X else X nc = DATUM(inst); X nc++; X if ( SV_BIT( *globals, channel ) ) X { X zread( infile, (char *)scanc, nc ); X if ( nc & 1 ) X (void)zgetc( infile ); /* throw away odd byte */ X } X else X { /* Emulate a forward fseek */ X register int ii; X for ( ii = ((nc + 1) / 2) * 2; ii > 0; ii-- ) X (void) zgetc( infile ); /* discard it */ X } X X scanc += nc; X scan_x += nc; X if ( debug_f ) X if ( SV_BIT( *globals, channel ) ) X { X rle_pixel * cp = scanc - nc; X fprintf( stderr, "Pixel data %d (to %d):", nc, scan_x ); X for ( ; nc > 0; nc-- ) X fprintf( stderr, "%02x", *cp++ ); X putc( '\n', stderr ); X } X else X fprintf( stderr, "Pixel data %d (to %d)\n", nc, scan_x ); X break; X X case RRunDataOp: X if ( LONGP(inst) ) X { X BREAD( short, long_data, sizeof long_data ); X SWAB( long_data ); X nc = long_data; X } X else X nc = DATUM(inst); X scan_x += nc + 1; X X BREAD( short, word, sizeof(short) ); X SWAB( word ); X if ( debug_f ) X fprintf( stderr, "Run length %d (to %d), data %02x\n", X nc + 1, scan_x, word ); X if ( SV_BIT( *globals, channel ) ) X { X if ( nc >= 10 ) /* break point for 785, anyway */ X { X bfill( (char *)scanc, nc + 1, word ); X scanc += nc + 1; X } X else X for ( ; nc >= 0; nc--, scanc++ ) X *scanc = word; X } X break; X X case REOFOp: X globals->sv_private.get.is_eof = 1; X break; X X default: X fprintf( stderr, X "rle_getrow: Unrecognized opcode: %d\n", inst.opcode ); X exit(1); X } X if ( OPCODE(inst) == RSkipLinesOp || OPCODE(inst) == REOFOp ) X break; /* <--- the other loop exit */ X } X X return globals->sv_private.get.scan_y; X} X X X/* Fill buffer at s with n copies of character c. N must be <= 65535*/ X/* ARGSUSED */ Xstatic void bfill( s, n, c ) Xchar *s; Xint n, c; X{ X#ifdef vax X asm(" movc5 $0,*4(ap),12(ap),8(ap),*4(ap)"); X#else X while ( n-- > 0 ) X *s++ = c; X#endif X} X X/* X * This software is copyrighted as noted below. It may be freely copied, X * modified, and redistributed, provided that the copyright notice is X * preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire X * to have all "void" functions so declared. X * X * Modified to generate an apropriate size dither map (ie 2x2, 4x4, 8x8 X * or 16x16) rather than use fixed 16x16 map. Use a large enough map X * to give a minimum of 128 effective levels rather than aiming for 256. X * This should give less grainy pictures. X * Two global variables can modify this: X * dith_levels = 128 (default) X * dith_np2 = 0 (default). Nonzero to enable non power of 2 dither mapping. X * dith_size = actual dither matrix size chosen. X * X * Graeme Gill 3 June 88 X */ X X/* X * dither.c - Functions for RGB color dithering. X * X * Author: Spencer W. Thomas X * Computer Science Dept. X * University of Utah X * Date: Mon Feb 2 1987 X * Copyright (c) 1987, University of Utah X */ X Xvoid make_square(); X X/* dither globals */ Xint dith_levels = 128; Xint dith_np2 = 0; Xint dith_size = 16; X X/* basic dithering macro */ X#define DMAP(v,x,y) (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v]) X X/***************************************************************** X * TAG( dithermap ) X * X * Create a color dithering map with a specified number of intensity levels. X * Inputs: X * levels: Intensity levels per primary. X * gamma: Display gamma value. X * Outputs: X * rgbmap: Generated color map. X * divN: "div" function for dithering. X * modN: "mod" function for dithering. X * Assumptions: X * rgbmap will hold levels^3 entries. X * Algorithm: X * Compute gamma compensation map. X * N = 255.0 / (levels - 1) is number of pixel values per level. X * Compute rgbmap with red ramping fastest, green slower, and blue X * slowest (treat it as if it were rgbmap[levels][levels][levels][3]). X * Call make_square to get divN, modN, and magic X * X * Note: X * Call dithergb( x, y, r, g, b, levels, divN, modN, magic ) to get index X * into rgbmap for a given color/location pair, or use X * row = y % 16; col = x % 16; X * DMAP(v,col,row) =def (divN[v] + (modN[v]>magic[col][row] ? 1 : 0)) X * DMAP(r,col,row) + DMAP(g,col,row)*levels + DMAP(b,col,row)*levels^2 X * if you don't want function call overhead. X */ Xvoid Xdithermap( levels, gamma, rgbmap, divN, modN, magic ) Xdouble gamma; Xint rgbmap[][3]; Xint divN[256]; Xint modN[256]; Xint magic[16][16]; X{ X double N, magicfact; X register int i, j, k, l; X int levelsq, levelsc; X int gammamap[256]; X X make_gamma(gamma,gammamap); X X levelsq = levels*levels; /* squared */ X levelsc = levels*levelsq; /* and cubed */ X X N = 255.0 / (levels - 1); /* Get size of each step */ X X /* X * Set up the color map entries. X */ X for(i = 0; i < levelsc; i++) { X rgbmap[i][0] = gammamap[(int)(0.5 + (i%levels) * N)]; X rgbmap[i][1] = gammamap[(int)(0.5 + ((i/levels)%levels) * N)]; X rgbmap[i][2] = gammamap[(int)(0.5 + ((i/levelsq)%levels) * N)]; X } X X make_square( N, divN, modN, magic ); X} X X X/***************************************************************** X * TAG( bwdithermap ) X * X * Create a color dithering map with a specified number of intensity levels. X * Inputs: X * levels: Intensity levels. X * gamma: Display gamma value. X * Outputs: X * bwmap: Generated black & white map. X * divN: "div" function for dithering. X * modN: "mod" function for dithering. X * Assumptions: X * bwmap will hold levels entries. X * Algorithm: X * Compute gamma compensation map. X * N = 255.0 / (levels - 1) is number of pixel values per level. X * Compute bwmap for levels entries. X * Call make_square to get divN, modN, and magic. X * Note: X * Call ditherbw( x, y, val, divN, modN, magic ) to get index into X * bwmap for a given color/location pair, or use X * row = y % 16; col = x % 16; X * divN[val] + (modN[val]>magic[col][row] ? 1 : 0) X * if you don't want function call overhead. X * On a 1-bit display, use X * divN[val] > magic[col][row] ? 1 : 0 X */ Xvoid Xbwdithermap( levels, gamma, bwmap, divN, modN, magic ) Xdouble gamma; Xint bwmap[]; Xint divN[256]; Xint modN[256]; Xint magic[16][16]; X{ X double N, magicfact; X register int i, j, k, l; X int gammamap[256]; X X make_gamma(gamma,gammamap); X X N = 255.0 / (levels - 1); /* Get size of each step */ X X /* X * Set up the color map entries. X */ X for(i = 0; i < levels; i++) X bwmap[i] = gammamap[(int)(0.5 + i * N)]; X X make_square( N, divN, modN, magic ); X} X X X/***************************************************************** X * TAG( make_square ) X * X * Build the magic square for a given number of levels. X * Inputs: X * N: Pixel values per level (255.0 / (levels-1)). X * (global) dith_levels = 128 (default) - number of effective levels to aim for X * (global) dith_np2 = 0 (default) - non-zero if non power of two size is permissable. X * Outputs: X * divN: Integer value of pixval / N X * modN: Integer remainder between pixval and divN[pixval]*N X * magic: Magic square for dithering to N sublevels. X * (global) dith_size = magic square size chosen. X * Assumptions: X * X * Algorithm: X * divN[pixval] = (int)(pixval / N) maps pixval to its appropriate level. X * modN[pixval] = pixval - (int)(N * divN[pixval]) maps pixval to X * its sublevel, and is used in the dithering computation. X */ Xvoid Xmake_square( N, divN, modN, magic ) Xdouble N; Xint divN[256]; Xint modN[256]; Xint magic[16][16] ; X{ X register int i, j, k, l; X double magicfact; X X for ( i = 0; i < 256; i++ ) X { X divN[i] = (int)(i / N); X modN[i] = i - (int)(N * divN[i]); X } X modN[255] = 0; /* always */ X X /* figure out how big a square will give */ X /* the desired number of levels */ X if(dith_np2) X for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size++ ); X else X for(dith_size= 2;((dith_size * dith_size)+1)<((N*dith_levels)/256);dith_size *=2); X X /* make the basic square up */ X /* ( will have numbers 0 - size * size ) */ X make_magic(dith_size,magic); X X /* divN gives 0 - levels-1 */ X /* modN gives 0 - N-1 */ X /* dither is if(modN(pix) > magic[][] so */ X /* scale magic it to have levels 0 to N-2 */ X /* (ie takes account of magic square size allows size * size +1 levels */ X X magicfact = (N-2)/((double)((dith_size * dith_size)-1)); X for(i=0;i<dith_size;i++) X { X for(j=0;j<dith_size;j++) X { X magic[i][j] = (int)(0.5 + magic[i][j] * magicfact); X } X } X X if(!dith_np2) /* if we have power of 2 */ X { X /* now replicate the size square we've chosen */ X /* (and use a brick pattern) */ X for(k=0;k<16;k += dith_size) X { X for(l=k>0?0:dith_size;l<16;l += dith_size) X { X for(i=0;i<dith_size;i++) X { X for(j=0;j<dith_size;j++) X { X magic[k+i][((l+k/2)+j)%16] = magic[i][j]; X } X } X } X } X } X} X Xint magic16x16[16][16] = X { X {0,128,32,160,8,136,40,168,2,130,34,162,10,138,42,170}, X {192,64,224,96,200,72,232,104,194,66,226,98,202,74,234,106}, X {48,176,16,144,56,184,24,152,50,178,18,146,58,186,26,154}, X {240,112,208,80,248,120,216,88,242,114,210,82,250,122,218,90}, X {12,140,44,172,4,132,36,164,14,142,46,174,6,134,38,166}, X {204,76,236,108,196,68,228,100,206,78,238,110,198,70,230,102}, X {60,188,28,156,52,180,20,148,62,190,30,158,54,182,22,150}, X {252,124,220,92,244,116,212,84,254,126,222,94,246,118,214,86}, X {3,131,35,163,11,139,43,171,1,129,33,161,9,137,41,169}, X {195,67,227,99,203,75,235,107,193,65,225,97,201,73,233,105}, X {51,179,19,147,59,187,27,155,49,177,17,145,57,185,25,153}, X {243,115,211,83,251,123,219,91,241,113,209,81,249,121,217,89}, X {15,143,47,175,7,135,39,167,13,141,45,173,5,133,37,165}, X {207,79,239,111,199,71,231,103,205,77,237,109,197,69,229,101}, X {63,191,31,159,55,183,23,151,61,189,29,157,53,181,21,149}, X {255,127,223,95,247,119,215,87,253,125,221,93,245,117,213,85} X }; X X/***************************************************************** X * TAG( make_magic ) X * X * Create the magic square. X * Inputs: X * size: Order of the square X * magic: Address of 16 x 16 magic square. X * Outputs: X * Fills in the 16 x 16 magic square. X * Assumptions: X * size is between 2 and 16 X * Algorithm: X * Chose sub cell of 16 by 16 magic square X */ Xmake_magic( size, magic ) Xint size; Xint magic[16][16]; X{ X int j,i,li,bi,bx,by; X int xx,yy; X int total; X X total = size * size; X X i = 0; X li = -1; X for(j=0;j<total;j++) X { X bi = 256; X X for(xx=0;xx<size;xx++) X { X for(yy=0;yy<size;yy++) X { X if(magic16x16[xx][yy] >li && magic16x16[xx][yy] < bi) X { X bx = xx; X by = yy; X bi = magic16x16[xx][yy]; X } X } X } X magic[bx][by] = i; X i++; X li = bi; X } X} X X/***************************************************************** X * TAG( make_gamma ) X * X * Makes a gamma compenstation map. X * Inputs: X * gamma: desired gamma X * gammamap: gamma mapping array X * Outputs: X * Changes gamma array entries. X */ Xmake_gamma( gamma, gammamap ) Xdouble gamma; Xint gammamap[256]; X{ X register int i; X X for ( i = 0; i < 256; i++ ) X { X#ifdef BYTEBUG X int byteb1; X X byteb1 = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma )); X gammamap[i] = byteb1; X#else X gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/gamma )); X#endif X } X} X X/***************************************************************** X * TAG( dithergb ) X * X * Return dithered RGB value. X * Inputs: X * x: X location on screen of this pixel. X * y: Y location on screen of this pixel. X * r, g, b: Color at this pixel (0 - 255 range). X * levels: Number of levels in this map. X * divN, modN: From dithermap. X * magic: Magic square from dithermap. X * Outputs: X * Returns color map index for dithered pixelv value. X * Assumptions: X * divN, modN, magic were set up properly. X * Algorithm: X * see "Note:" in dithermap comment. X */ Xdithergb( x, y, r, g, b, levels, divN, modN, magic ) Xint divN[256]; Xint modN[256]; Xint magic[16][16]; X{ X int col = x % 16, row = y % 16; X X return DMAP(r, col, row) + X DMAP(g, col, row) * levels + X DMAP(b, col, row) * levels*levels; X} X X X/***************************************************************** X * TAG( ditherbw ) X * X * Return dithered black & white value. X * Inputs: X * x: X location on screen of this pixel. X * y: Y location on screen of this pixel. X * val: Intensity at this pixel (0 - 255 range). X * divN, modN: From dithermap. X * magic: Magic square from dithermap. X * Outputs: X * Returns color map index for dithered pixel value. X * Assumptions: X * divN, modN, magic were set up properly. X * Algorithm: X * see "Note:" in bwdithermap comment. X */ Xditherbw( x, y, val, divN, modN, magic ) Xint divN[256]; Xint modN[256]; Xint magic[16][16]; X{ X int col = x % 16, row = y % 16; X X return DMAP(val, col, row); X} END_OF_FILE if test 50248 -ne `wc -c <'rlelib.c'`; then echo shar: \"'rlelib.c'\" unpacked with wrong size! fi # end of 'rlelib.c' fi echo shar: End of archive 7 \(of 9\). cp /dev/null ark7isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 9 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.