v09i054: xloadimage, Part07/09
saber.com!jimf at saber.com
saber.com!jimf at saber.com
Fri Sep 28 11:55:56 AEST 1990
Submitted-by: saber.com!jimf at 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 at 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 at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list