DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦18568bf0d⟧ TextFile

    Length: 30047 (0x755f)
    Types: TextFile
    Names: »sample.c«

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦this⟧ »./DVIware/crt-viewers/others/sample.c« 
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/crt-viewers/sunview/dvipage/sample.c« 

TextFile

/*
 * dvipage: DVI Previewer Program for Suns
 *
 * Neil Hunt (hunt@spar.slb.com)
 *
 * This program is based, in part, upon the program dvisun,
 * distributed by the UnixTeX group, extensively modified by
 * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
 * of Schlumberger Technologies, Inc.
 *
 * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
 * Anyone can use this software in any manner they choose,
 * including modification and redistribution, provided they make
 * no charge for it, and these conditions remain unchanged.
 *
 * This program is distributed as is, with all faults (if any), and
 * without any warranty. No author or distributor accepts responsibility
 * to anyone for the consequences of using it, or for whether it serves any
 * particular purpose at all, or any other reason.
 *
 * $Log:	sample.c,v $
 * Revision 1.1  88/11/28  18:41:24  hunt
 * Initial revision
 * 
 * Split out of dvipage.c version 1.4.
 */

#include <stdio.h>
#include <sys/param.h>		/* For MAXPATHLEN */
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include "dvipage.h"

forward struct pixrect *	pr_alloc();
forward struct pixrect *	pr_free();
forward struct pixrect *	pr_check();
forward struct pixrect *	pr_link();
forward struct pixrect *	pr_sample_4();
forward struct pixrect *	pr_sample_34();
forward struct pixrect *	pr_sample_3();
forward struct pixrect *	pr_sample_2();

forward void			pw_cover();
forward void			pr_rect();
forward void			pw_rect();

/*
 * sample_page:
 *	Filter and sample down page according to current sampling rate,
 *	and prepare for display.
 */

void
sample_page()
{

#ifdef TIMING
	start_time();
#endif TIMING

	switch(sampling)
	{
	default:
	case 1:
		sample_pr = pr_link(&page_mpr, &sample_mpr);
		break;

	case 2:
		if(! (sample_pr = pr_sample_2(&page_mpr, &sample_mpr)))
			message("Out of memory for resampling image");
		break;

	case 3:
		if(! (sample_pr = pr_sample_3(&page_mpr, &sample_mpr)))
			message("Out of memory for resampling image");
		break;

	case 4:
		if(! (sample_pr = pr_sample_4(&page_mpr, &sample_mpr)))
			message("Out of memory for resampling image");
		break;

	case 5:
		if(! (sample_pr = pr_sample_34(&page_mpr, &sample_mpr)))
			message("Out of memory for resampling image");
		break;
	}

#ifdef TIMING
	stop_time("Sampling one page");
#endif TIMING

}

/*
 * Here follow some functions to deal with pixrects under the special case
 * assumption that they are mem_pixrects, where the mpr_data is part
 * of a parent structure.
 */

extern struct pixrectops mem_ops;

/*
 * pr_alloc:
 *	Allocate memory for a pixrect of size w, h, d.
 *	Returns a pointer to the pixrect structure.
 */

struct pixrect *
pr_alloc(mpr, w, h, d)
struct mem_pixrect *mpr;
int w, h, d;
{
	int size;
	int linebytes;
	short *image;

	/*
	 * Compute the size of memory needed, and alloc it.
	 */
	linebytes = mpr_linebytes(w, d);
	size = linebytes * h;
	if(! (image = (short *)malloc(size)))
		return (struct pixrect *)NULL;

	/*
	 * Set up the pr.
	 */
	mpr->mpr_pr.pr_ops = &mem_ops;
	mpr->mpr_pr.pr_width = w;
	mpr->mpr_pr.pr_height = h;
	mpr->mpr_pr.pr_depth = d;
	mpr->mpr_pr.pr_data = (caddr_t)&mpr->mpr_data;

	/*
	 * Set up the mpr_data
	 */
	mpr->mpr_data.md_linebytes = linebytes;
	mpr->mpr_data.md_image = image;
	mpr->mpr_data.md_offset.x = 0;
	mpr->mpr_data.md_offset.y = 0;
	mpr->mpr_data.md_primary = TRUE;
	mpr->mpr_data.md_flags = 0;

	/*
	 * Return the pr.
	 */
	return &mpr->mpr_pr;
}

/*
 * pr_free:
 *	Free the memory associated with a pixrect.
 *	Returns a pointer to no pixrect structure.
 */

struct pixrect *
pr_free(mpr)
struct mem_pixrect *mpr;
{
	short *image;

	if((image = mpr->mpr_data.md_image))
	{
		if(mpr->mpr_data.md_primary)
			free(image);
		mpr->mpr_data.md_image = (short *)NULL;
	}
	mpr->mpr_pr.pr_width = 0;
	mpr->mpr_pr.pr_height = 0;

	return (struct pixrect *)NULL;
}

/*
 * pr_check:
 *	Check that a designated pixrect has memory allocated for an image
 *	of size w, h, d. If not, free any existing memory and allocate
 *	more memory. This is equivalent to, but much faster than, a
 *	sequence of
 *		pr_destroy(mpr);
 *		mpr = mem_create(w, h, d);
 */

struct pixrect *
pr_check(mpr, w, h, d)
struct mem_pixrect *mpr;
int w, h, d;
{
	/*
	 * If there is an image, check that it is the correct size.
	 */
	if(mpr->mpr_data.md_image)
	{
		if(mpr->mpr_pr.pr_width == w &&
		  mpr->mpr_pr.pr_height == h &&
		  mpr->mpr_pr.pr_depth == d)
			return &mpr->mpr_pr;

		(void)pr_free(mpr);
	}

	return pr_alloc(mpr, w, h, d);
}

/*
 * pr_link:
 *	Link the memory of mpr1 to mpr2, making mpr2 a secondary pixrect.
 */

struct pixrect *
pr_link(mpr1, mpr2)
struct mem_pixrect *mpr1;
struct mem_pixrect *mpr2;
{
	/*
	 * Free the existing memory, if any.
	 */
	(void)pr_free(mpr2);

	/*
	 * Set up the pr.
	 */
	mpr2->mpr_pr.pr_ops = &mem_ops;
	mpr2->mpr_pr.pr_width = mpr1->mpr_pr.pr_width;
	mpr2->mpr_pr.pr_height = mpr1->mpr_pr.pr_height;
	mpr2->mpr_pr.pr_depth = mpr1->mpr_pr.pr_depth;
	mpr2->mpr_pr.pr_data = (caddr_t)&mpr2->mpr_data;

	/*
	 * Set up the mpr_data
	 */
	mpr2->mpr_data.md_linebytes = mpr1->mpr_data.md_linebytes;
	mpr2->mpr_data.md_image = mpr1->mpr_data.md_image;
	mpr2->mpr_data.md_offset.x = mpr1->mpr_data.md_offset.x;
	mpr2->mpr_data.md_offset.y = mpr1->mpr_data.md_offset.y;
	mpr2->mpr_data.md_primary = FALSE;
	mpr2->mpr_data.md_flags = 0;

	/*
	 * Return the pr.
	 */
	return &mpr2->mpr_pr;
}
\f


/*
 * Colour Map Stuff
 * ================
 */

#define M4F	0
#define M4T	(M4F+16)
#define M3F	(M4T+1)
#define M3T	(M3F+24)
#define M2F	(M3T+1)
#define M2T	(M2F+4)

uchar	cmap_red[64] =
{
#ifdef NEVER
	/* Cmap with GAMMA=2,2,2,20,20,20 */
	/* 4x4 from 0 to 16 */
	255, 247, 239, 231, 223, 214, 205, 196, 186,
	175, 163, 151, 137, 121, 103, 78, 20,

	/* 3x3 from 17 to 41 */
	255, 250, 244, 239, 234, 229, 223, 217, 211,
	205, 199, 192, 186, 179, 171, 163, 155,
	146, 137, 127, 115, 103, 87, 67, 20,

	/* 2x2 from 42 to 46 */
	255, 223, 186, 137, 20,

	/* spare */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#endif NEVER
	/* Cmap with GAMMA=1.3,1.3,1.3,0,0,0 */
	/* 4x4 from 0 to 16 */
	255, 242, 230, 217, 204, 191, 177, 163, 149,
	135, 119, 104,  87,  70,  51,  30,   0,

	/* 3x3 from 17 to 41 */
	255, 246, 238, 230, 221, 213, 204, 195, 186,
	177, 168, 159, 149, 139, 130, 119, 109,
	 98,  87,  76,  64,  51,  37,  22,   0,

	/* 2x2 from 42 to 46 */
	255, 204, 149,  87,   0,

	/* spare */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

uchar	cmap_green[64] =
{
	/* 4x4 from 0 to 16 */
	255, 242, 230, 217, 204, 191, 177, 163, 149,
	135, 119, 104,  87,  70,  51,  30,   0,

	/* 3x3 from 17 to 41 */
	255, 246, 238, 230, 221, 213, 204, 195, 186,
	177, 168, 159, 149, 139, 130, 119, 109,
	 98,  87,  76,  64,  51,  37,  22,   0,

	/* 2x2 from 42 to 46 */
	255, 204, 149,  87,   0,

	/* spare */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

uchar	cmap_blue[64] =
{
	/* 4x4 from 0 to 16 */
	255, 242, 230, 217, 204, 191, 177, 163, 149,
	135, 119, 104,  87,  70,  51,  30,   0,

	/* 3x3 from 17 to 41 */
	255, 246, 238, 230, 221, 213, 204, 195, 186,
	177, 168, 159, 149, 139, 130, 119, 109,
	 98,  87,  76,  64,  51,  37,  22,   0,

	/* 2x2 from 42 to 46 */
	255, 204, 149,  87,   0,

	/* spare */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

double			gamma_red = 2.0;
double			gamma_green = 2.0;
double			gamma_blue = 2.0;
int			min_red = 20;
int			min_green = 20;
int			min_blue = 20;

forward void		make_one_cmap();

void
make_cmap()
{
	char *e;

	if((e = getenv("DVIPAGE_GAMMA")) == NULL)
		return;

	min_red = 20;
	min_green = 20;
	min_blue = 20;
	gamma_red = 0.0;
	gamma_green = 0.0;
	gamma_blue = 0.0;

	(void)sscanf(e, " %lf,%lf,%lf,%d,%d,%d ",
	  &gamma_red, &gamma_green, &gamma_blue,
	  &min_red, &min_green, &min_blue);

	if(gamma_red == 0.0)
		gamma_red = 1.3;
	if(gamma_green == 0.0)
		gamma_green = gamma_red;
	if(gamma_blue == 0.0)
		gamma_blue = gamma_red;

	make_one_cmap(cmap_red, 1.0/gamma_red, min_red);
	make_one_cmap(cmap_green, 1.0/gamma_green, min_green);
	make_one_cmap(cmap_blue, 1.0/gamma_blue, min_blue);
}

void
make_one_cmap(cmap, power, mn)
uchar cmap[];
double power;
int mn;
{
	int i;

	/*
	 * 4x4 cmap.
	 */
	for(i = M4F; i <= M4T; i++)
		cmap[i] = (uchar)(pow((double)(M4T - i) / (M4T - M4F), power)
		  * (255 - mn) + mn);

	/*
	 * 3x3 cmap.
	 */
	for(i = M3F; i <= M3T; i++)
		cmap[i] = (uchar)(pow((double)(M3T - i) / (M3T - M3F), power)
		  * (255 - mn) + mn);

	/*
	 * 2x2 cmap.
	 */
	for(i = M2F; i <= M2T; i++)
		cmap[i] = (uchar)(pow((double)(M2T - i) / (M2T - M2F), power)
		  * (255 - mn) + mn);

	cmap[63] = mn;
}

/*
 * Tally table used to compute the number of bits in packed words.
 * This is used in computing the number of bits in a 4x4 region of
 * a packed image.
 *
 * The packed word is used as an index into this table;
 * The most significant 16 bits of the value obtained represent the
 * number of bits in the upper half of the index, with each bit counted
 * with a weight of 15.
 * The least significant 16 bits of the value obtained represent the
 * number of bits in the l;ower hald of the index, with each bit counted
 * with a weight of 15.
 *
 * By combining the upper and lower halves in a single word, the values
 * for the four vertically adjacent words can be combined with each other
 * in a single addition per word, adding simultaneously both the tallies
 * for the left and the right halves of the word.
 */

static int tally4[] =
{
	0x00000000, 0x00000001, 0x00000001, 0x00000002,
	0x00000001, 0x00000002, 0x00000002, 0x00000003,
	0x00000001, 0x00000002, 0x00000002, 0x00000003,
	0x00000002, 0x00000003, 0x00000003, 0x00000004,
	0x00010000, 0x00010001, 0x00010001, 0x00010002,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010002, 0x00010003, 0x00010003, 0x00010004,
	0x00010000, 0x00010001, 0x00010001, 0x00010002,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010002, 0x00010003, 0x00010003, 0x00010004,
	0x00020000, 0x00020001, 0x00020001, 0x00020002,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020002, 0x00020003, 0x00020003, 0x00020004,
	0x00010000, 0x00010001, 0x00010001, 0x00010002,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010002, 0x00010003, 0x00010003, 0x00010004,
	0x00020000, 0x00020001, 0x00020001, 0x00020002,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020002, 0x00020003, 0x00020003, 0x00020004,
	0x00020000, 0x00020001, 0x00020001, 0x00020002,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020002, 0x00020003, 0x00020003, 0x00020004,
	0x00030000, 0x00030001, 0x00030001, 0x00030002,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030002, 0x00030003, 0x00030003, 0x00030004,
	0x00010000, 0x00010001, 0x00010001, 0x00010002,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010001, 0x00010002, 0x00010002, 0x00010003,
	0x00010002, 0x00010003, 0x00010003, 0x00010004,
	0x00020000, 0x00020001, 0x00020001, 0x00020002,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020002, 0x00020003, 0x00020003, 0x00020004,
	0x00020000, 0x00020001, 0x00020001, 0x00020002,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020002, 0x00020003, 0x00020003, 0x00020004,
	0x00030000, 0x00030001, 0x00030001, 0x00030002,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030002, 0x00030003, 0x00030003, 0x00030004,
	0x00020000, 0x00020001, 0x00020001, 0x00020002,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020001, 0x00020002, 0x00020002, 0x00020003,
	0x00020002, 0x00020003, 0x00020003, 0x00020004,
	0x00030000, 0x00030001, 0x00030001, 0x00030002,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030002, 0x00030003, 0x00030003, 0x00030004,
	0x00030000, 0x00030001, 0x00030001, 0x00030002,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030001, 0x00030002, 0x00030002, 0x00030003,
	0x00030002, 0x00030003, 0x00030003, 0x00030004,
	0x00040000, 0x00040001, 0x00040001, 0x00040002,
	0x00040001, 0x00040002, 0x00040002, 0x00040003,
	0x00040001, 0x00040002, 0x00040002, 0x00040003,
	0x00040002, 0x00040003, 0x00040003, 0x00040004,
};

/*
 * Tally table used to compute the number of bits in packed words.
 * This is used in computing the number of bits in a 3x3 region of
 * a packed image.
 *
 * The packed word is used as an index into this table;
 * Bits 23..16 of the value obtained represent the number of bits in
 * the upper 2.67 bits of the index, with each bit counted with a weight
 * of 15. etc. etc.
 *
 * By combining the three parts in a single word, the values
 * for the three vertically adjacent words can be combined with each other
 * in a single addition per word, adding simultaneously both the tallies
 * for the left and the right halves of the word.
 */

static int tally3[] =
{
	0x00000000, 0x00000003, 0x00000003, 0x00000006,
	0x00000102, 0x00000105, 0x00000105, 0x00000108,
	0x00000300, 0x00000303, 0x00000303, 0x00000306,
	0x00000402, 0x00000405, 0x00000405, 0x00000408,
	0x00000300, 0x00000303, 0x00000303, 0x00000306,
	0x00000402, 0x00000405, 0x00000405, 0x00000408,
	0x00000600, 0x00000603, 0x00000603, 0x00000606,
	0x00000702, 0x00000705, 0x00000705, 0x00000708,
	0x00020100, 0x00020103, 0x00020103, 0x00020106,
	0x00020202, 0x00020205, 0x00020205, 0x00020208,
	0x00020400, 0x00020403, 0x00020403, 0x00020406,
	0x00020502, 0x00020505, 0x00020505, 0x00020508,
	0x00020400, 0x00020403, 0x00020403, 0x00020406,
	0x00020502, 0x00020505, 0x00020505, 0x00020508,
	0x00020700, 0x00020703, 0x00020703, 0x00020706,
	0x00020802, 0x00020805, 0x00020805, 0x00020808,
	0x00030000, 0x00030003, 0x00030003, 0x00030006,
	0x00030102, 0x00030105, 0x00030105, 0x00030108,
	0x00030300, 0x00030303, 0x00030303, 0x00030306,
	0x00030402, 0x00030405, 0x00030405, 0x00030408,
	0x00030300, 0x00030303, 0x00030303, 0x00030306,
	0x00030402, 0x00030405, 0x00030405, 0x00030408,
	0x00030600, 0x00030603, 0x00030603, 0x00030606,
	0x00030702, 0x00030705, 0x00030705, 0x00030708,
	0x00050100, 0x00050103, 0x00050103, 0x00050106,
	0x00050202, 0x00050205, 0x00050205, 0x00050208,
	0x00050400, 0x00050403, 0x00050403, 0x00050406,
	0x00050502, 0x00050505, 0x00050505, 0x00050508,
	0x00050400, 0x00050403, 0x00050403, 0x00050406,
	0x00050502, 0x00050505, 0x00050505, 0x00050508,
	0x00050700, 0x00050703, 0x00050703, 0x00050706,
	0x00050802, 0x00050805, 0x00050805, 0x00050808,
	0x00030000, 0x00030003, 0x00030003, 0x00030006,
	0x00030102, 0x00030105, 0x00030105, 0x00030108,
	0x00030300, 0x00030303, 0x00030303, 0x00030306,
	0x00030402, 0x00030405, 0x00030405, 0x00030408,
	0x00030300, 0x00030303, 0x00030303, 0x00030306,
	0x00030402, 0x00030405, 0x00030405, 0x00030408,
	0x00030600, 0x00030603, 0x00030603, 0x00030606,
	0x00030702, 0x00030705, 0x00030705, 0x00030708,
	0x00050100, 0x00050103, 0x00050103, 0x00050106,
	0x00050202, 0x00050205, 0x00050205, 0x00050208,
	0x00050400, 0x00050403, 0x00050403, 0x00050406,
	0x00050502, 0x00050505, 0x00050505, 0x00050508,
	0x00050400, 0x00050403, 0x00050403, 0x00050406,
	0x00050502, 0x00050505, 0x00050505, 0x00050508,
	0x00050700, 0x00050703, 0x00050703, 0x00050706,
	0x00050802, 0x00050805, 0x00050805, 0x00050808,
	0x00060000, 0x00060003, 0x00060003, 0x00060006,
	0x00060102, 0x00060105, 0x00060105, 0x00060108,
	0x00060300, 0x00060303, 0x00060303, 0x00060306,
	0x00060402, 0x00060405, 0x00060405, 0x00060408,
	0x00060300, 0x00060303, 0x00060303, 0x00060306,
	0x00060402, 0x00060405, 0x00060405, 0x00060408,
	0x00060600, 0x00060603, 0x00060603, 0x00060606,
	0x00060702, 0x00060705, 0x00060705, 0x00060708,
	0x00080100, 0x00080103, 0x00080103, 0x00080106,
	0x00080202, 0x00080205, 0x00080205, 0x00080208,
	0x00080400, 0x00080403, 0x00080403, 0x00080406,
	0x00080502, 0x00080505, 0x00080505, 0x00080508,
	0x00080400, 0x00080403, 0x00080403, 0x00080406,
	0x00080502, 0x00080505, 0x00080505, 0x00080508,
	0x00080700, 0x00080703, 0x00080703, 0x00080706,
	0x00080802, 0x00080805, 0x00080805, 0x00080808,
};

/*
 * Tally table used to compute the number of bits in packed words.
 * This is used in computing the number of bits in a 2x2 region of
 * a packed image.
 *
 * The packed word is used as an index into this table;
 * The most significant 8 bits of the value obtained represent the
 * number of bits in the upper half of the index, with each bit counted
 * with a weight of 15.
 * ...
 * The least significant 8 bits of the value obtained represent the
 * number of bits in the l;ower hald of the index, with each bit counted
 * with a weight of 15.
 *
 * By combining the four pairs of tallies in a single word, the values
 * for the two vertically adjacent words can be combined with each other
 * in a single addition per word, adding simultaneously all four tallies
 * for the four pairs of the word.
 */

static int tally2[] =
{
	0x00000000, 0x00000001, 0x00000001, 0x00000002,
	0x00000100, 0x00000101, 0x00000101, 0x00000102,
	0x00000100, 0x00000101, 0x00000101, 0x00000102,
	0x00000200, 0x00000201, 0x00000201, 0x00000202,
	0x00010000, 0x00010001, 0x00010001, 0x00010002,
	0x00010100, 0x00010101, 0x00010101, 0x00010102,
	0x00010100, 0x00010101, 0x00010101, 0x00010102,
	0x00010200, 0x00010201, 0x00010201, 0x00010202,
	0x00010000, 0x00010001, 0x00010001, 0x00010002,
	0x00010100, 0x00010101, 0x00010101, 0x00010102,
	0x00010100, 0x00010101, 0x00010101, 0x00010102,
	0x00010200, 0x00010201, 0x00010201, 0x00010202,
	0x00020000, 0x00020001, 0x00020001, 0x00020002,
	0x00020100, 0x00020101, 0x00020101, 0x00020102,
	0x00020100, 0x00020101, 0x00020101, 0x00020102,
	0x00020200, 0x00020201, 0x00020201, 0x00020202,
	0x01000000, 0x01000001, 0x01000001, 0x01000002,
	0x01000100, 0x01000101, 0x01000101, 0x01000102,
	0x01000100, 0x01000101, 0x01000101, 0x01000102,
	0x01000200, 0x01000201, 0x01000201, 0x01000202,
	0x01010000, 0x01010001, 0x01010001, 0x01010002,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010200, 0x01010201, 0x01010201, 0x01010202,
	0x01010000, 0x01010001, 0x01010001, 0x01010002,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010200, 0x01010201, 0x01010201, 0x01010202,
	0x01020000, 0x01020001, 0x01020001, 0x01020002,
	0x01020100, 0x01020101, 0x01020101, 0x01020102,
	0x01020100, 0x01020101, 0x01020101, 0x01020102,
	0x01020200, 0x01020201, 0x01020201, 0x01020202,
	0x01000000, 0x01000001, 0x01000001, 0x01000002,
	0x01000100, 0x01000101, 0x01000101, 0x01000102,
	0x01000100, 0x01000101, 0x01000101, 0x01000102,
	0x01000200, 0x01000201, 0x01000201, 0x01000202,
	0x01010000, 0x01010001, 0x01010001, 0x01010002,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010200, 0x01010201, 0x01010201, 0x01010202,
	0x01010000, 0x01010001, 0x01010001, 0x01010002,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010100, 0x01010101, 0x01010101, 0x01010102,
	0x01010200, 0x01010201, 0x01010201, 0x01010202,
	0x01020000, 0x01020001, 0x01020001, 0x01020002,
	0x01020100, 0x01020101, 0x01020101, 0x01020102,
	0x01020100, 0x01020101, 0x01020101, 0x01020102,
	0x01020200, 0x01020201, 0x01020201, 0x01020202,
	0x02000000, 0x02000001, 0x02000001, 0x02000002,
	0x02000100, 0x02000101, 0x02000101, 0x02000102,
	0x02000100, 0x02000101, 0x02000101, 0x02000102,
	0x02000200, 0x02000201, 0x02000201, 0x02000202,
	0x02010000, 0x02010001, 0x02010001, 0x02010002,
	0x02010100, 0x02010101, 0x02010101, 0x02010102,
	0x02010100, 0x02010101, 0x02010101, 0x02010102,
	0x02010200, 0x02010201, 0x02010201, 0x02010202,
	0x02010000, 0x02010001, 0x02010001, 0x02010002,
	0x02010100, 0x02010101, 0x02010101, 0x02010102,
	0x02010100, 0x02010101, 0x02010101, 0x02010102,
	0x02010200, 0x02010201, 0x02010201, 0x02010202,
	0x02020000, 0x02020001, 0x02020001, 0x02020002,
	0x02020100, 0x02020101, 0x02020101, 0x02020102,
	0x02020100, 0x02020101, 0x02020101, 0x02020102,
	0x02020200, 0x02020201, 0x02020201, 0x02020202,
};

/*
 * P_row:
 *	Access macro for obtaining a pointer to the bytes of a pixrect
 *	starting at row `row'.
 */

#define P_row(mpr, row) \
	(uchar *)((int)((mpr)->mpr_data.md_image) + \
	  (int)((short)(row) * (short)((mpr)->mpr_data.md_linebytes)));

/*
 * pr_sample_4:
 *	Filter and sample mpr1 on a 4x4 basis into mpr2.
 */

struct pixrect *
pr_sample_4(mpr1, mpr2)
struct mem_pixrect *mpr1;
struct mem_pixrect *mpr2;
{
	int cols, rows;
	int j;
	register uchar *p0;		/* a5 */
	register uchar *p1;		/* a4 */
	register uchar *p2;		/* a3 */
	register uchar *p3;		/* a2 */
	register uchar *pr;
	register uchar *er;
	register int tallies;		/* d7 */
	int line_offset;

	cols = mpr1->mpr_pr.pr_width / 4;
	rows = mpr1->mpr_pr.pr_height / 4;

	if(verbose & DEBUG_IMSIZE)
		fprintf(stderr, "pr_sample_4: (%d x %d) -> (%d x %d)\n",
		  mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);

	/*
	 * Allocate output image.
	 */
	if(! pr_check(mpr2, cols, rows, 8))
		return (struct pixrect *)NULL;

	/*
	 * Do the sampling.
	 */
	line_offset = mpr1->mpr_data.md_linebytes;
	for(j = 0; j < rows; j++)
	{
		p0 = P_row(mpr1, j*4);
		p1 = p0 + line_offset;
		p2 = p1 + line_offset;
		p3 = p2 + line_offset;

		pr = P_row(mpr2, j);

		for(er = pr + cols; pr < er; )
		{
			/*
			 * Test for all zero.
			if(*p0 == 0 && *p1 == 0 && *p2 == 0 && *p3 == 0)
			{
				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;
			}
			else
			 */
			{
				tallies =
				  tally4[*p0] +
				  tally4[*p1] +
				  tally4[*p2] +
				  tally4[*p3];

				/*
				 * High order 4 bits
				 */
				*pr++ = (tallies >> 16) + M4F;

				if(pr >= er)
					break;

				/*
				 * Low order 4 bits
				 */
				*pr++ = tallies + M4F;
			}
			p0++;
			p1++;
			p2++;
			p3++;
		}
	}

	return &mpr2->mpr_pr;
}

/*
 * pr_sample_34:
 *	Filter and sample mpr1 on a 2.67x4 basis into mpr2.
 *	Tally count uses M3 table, and gets up to 32 pixels (weighted at 1/3)
 *	  divides by two to index into the 0..16 M4 table.
 */

struct pixrect *
pr_sample_34(mpr1, mpr2)
struct mem_pixrect *mpr1;
struct mem_pixrect *mpr2;
{
	int cols, rows;
	int j;
	register uchar *p0;		/* a5 */
	register uchar *p1;		/* a4 */
	register uchar *p2;		/* a3 */
	register uchar *p3;		/* a2 */
	register uchar *pr;
	register uchar *er;
	register int tallies;		/* d7 */
	int line_offset;

	cols = mpr1->mpr_pr.pr_width * 3 / 8;
	rows = mpr1->mpr_pr.pr_height / 4;

	if(verbose & DEBUG_IMSIZE)
		fprintf(stderr, "pr_sample_34: (%d x %d) -> (%d x %d)\n",
		  mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);

	/*
	 * Allocate output image.
	 */
	if(! pr_check(mpr2, cols, rows, 8))
		return (struct pixrect *)NULL;

	/*
	 * Do the sampling.
	 */
	line_offset = mpr1->mpr_data.md_linebytes;
	for(j = 0; j < rows; j++)
	{
		p0 = P_row(mpr1, j*4);
		p1 = p0 + line_offset;
		p2 = p1 + line_offset;
		p3 = p2 + line_offset;

		pr = P_row(mpr2, j);

		for(er = pr + cols; pr < er; )
		{
			/*
			 * Test for all zero.
			if(*p0 == 0 && *p1 == 0 && *p2 == 0)
			{
				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;
			}
			else
			 */
			{
				tallies =
				  tally3[*p0] +
				  tally3[*p1] +
				  tally3[*p2] +
				  tally3[*p3];

				/*
				 * High order 3 bits
				 */
				*pr++ = (tallies >> (16+1)) + M4F;

				if(pr >= er)
					break;

				*pr++ = (tallies >> (8+1)) + M4F;

				if(pr >= er)
					break;

				/*
				 * Low order 3 bits
				 */
				*pr++ = (tallies >> 1) + M4F;
			}
			p0++;
			p1++;
			p2++;
			p3++;
		}
	}

	return &mpr2->mpr_pr;
}

/*
 * pr_sample_3:
 *	Filter and sample mpr1 on a 3x3 basis into mpr2.
 *	Note that the horizontal sampling is actually 3/8 rather than 1/3.
 */

struct pixrect *
pr_sample_3(mpr1, mpr2)
struct mem_pixrect *mpr1;
struct mem_pixrect *mpr2;
{
	int cols, rows;
	int j;
	register uchar *p0;		/* a5 */
	register uchar *p1;		/* a4 */
	register uchar *p2;		/* a3 */
	register uchar *pr;		/* a2 */
	register uchar *er;
	register int tallies;		/* d7 */
	int line_offset;

	cols = mpr1->mpr_pr.pr_width * 3 / 8;
	rows = mpr1->mpr_pr.pr_height / 3;

	if(verbose & DEBUG_IMSIZE)
		fprintf(stderr, "pr_sample_3: (%d x %d) -> (%d x %d)\n",
		  mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);

	/*
	 * Allocate output image.
	 */
	if(! pr_check(mpr2, cols, rows, 8))
		return (struct pixrect *)NULL;

	/*
	 * Do the sampling.
	 */
	line_offset = mpr1->mpr_data.md_linebytes;
	for(j = 0; j < rows; j++)
	{
		p0 = P_row(mpr1, j*3);
		p1 = p0 + line_offset;
		p2 = p1 + line_offset;

		pr = P_row(mpr2, j);

		for(er = pr + cols; pr < er; )
		{
			/*
			 * Test for all zero.
			if(*p0 == 0 && *p1 == 0 && *p2 == 0)
			{
				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;
			}
			else
			 */
			{
				tallies =
				  tally3[*p0] +
				  tally3[*p1] +
				  tally3[*p2];

				/*
				 * High order 3 bits
				 */
				*pr++ = (tallies >> 16) + M3F;

				if(pr >= er)
					break;

				*pr++ = (tallies >> 8) + M3F;

				if(pr >= er)
					break;

				/*
				 * Low order 3 bits
				 */
				*pr++ = tallies + M3F;
			}
			p0++;
			p1++;
			p2++;
		}
	}

	return &mpr2->mpr_pr;
}

/*
 * pr_sample_2:
 *	Filter and sample mpr1 on a 2x2 basis into mpr2.
 */

struct pixrect *
pr_sample_2(mpr1, mpr2)
struct mem_pixrect *mpr1;
struct mem_pixrect *mpr2;
{
	int cols, rows;
	int j;
	register uchar *p0;		/* a5 */
	register uchar *p1;		/* a4 */
	register uchar *pr;		/* a3 */
	register uchar *er;		/* a2 */
	register int tallies;		/* d7 */
	int line_offset;

	cols = mpr1->mpr_pr.pr_width / 2;
	rows = mpr1->mpr_pr.pr_height / 2;

	if(verbose & DEBUG_IMSIZE)
		fprintf(stderr, "pr_sample_2: (%d x %d) -> (%d x %d)\n",
		  mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);

	/*
	 * Allocate output image.
	 */
	if(! pr_check(mpr2, cols, rows, 8))
		return (struct pixrect *)NULL;

	/*
	 * Do the sampling.
	 */
	line_offset = mpr1->mpr_data.md_linebytes;
	for(j = 0; j < rows; j++)
	{
		p0 = P_row(mpr1, j*2);
		p1 = p0 + line_offset;

		pr = P_row(mpr2, j);

		for(er = pr + cols; pr < er; )
		{
			/*
			 * Test for all zero.
			if(*p0 == 0 && *p1 == 0)
			{
				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;

				if(pr >= er)
					break;

				*pr++ = 0;
			}
			else
			 */
			{
				tallies =
				  tally2[*p0] +
				  tally2[*p1];

				/*
				 * Highest two bits
				 */
				*pr++ = (tallies >> 24) + M2F;

				if(pr >= er)
					break;

				*pr++ = (tallies >> 16) + M2F;

				if(pr >= er)
					break;

				*pr++ = (tallies >> 8) + M2F;

				if(pr >= er)
					break;

				/*
				 * Lowest two bits
				 */
				*pr++ = tallies + M2F;
			}
			p0++;
			p1++;
		}
	}

	return &mpr2->mpr_pr;
}

/*
 * pw_cover:
 *	Function which writes a pixrect onto a pixwin;
 *	where there are no src pixels, it writes background colour.
 */

void
pw_cover(dpw, dx, dy, dw, dh, op, spr, sx, sy)
Pixwin *dpw;
int dx, dy, dw, dh;
int op;
Pixrect *spr;
int sx, sy;
{
	int aw, ah;

	/*
	 * Handle the left margin.
	 * If the left margin is less than the width to be painted,
	 * paint a margin, else paint the whole region and return.
	 */
	if(sx < 0)
	{
		if(-sx < dw)
		{
			pw_writebackground(dpw, dx, dy, -sx, dh, op);
			dx -= sx;
			sx = 0;
			dw += sx;
		}
		else
		{
			pw_writebackground(dpw, dx, dy, dw, dh, op);
			return;
		}
	}

	/*
	 * Handle the top margin.
	 * If the top margin is less thatn the width to be painted,
	 * paint a margin, else paint the whole region and return.
	 */
	if(sy < 0)
	{
		if(-sy < dh)
		{
			pw_writebackground(dpw, dx, dy, dw, -sy, op);
			dy -= sy;
			sy = 0;
			dh += sy;
		}
		else
		{
			pw_writebackground(dpw, dx, dy, dw, dh, op);
			return;
		}
	}

	/*
	 * Handle the right margin.
	 * aw = available width of source image.
	 * If available width > 0 paint a margin of dw-aw width,
	 * otherwise paint the whole region.
	 */
	aw = spr->pr_width-sx;
	if(dw > aw)
	{
		if(aw > 0)
		{
			pw_writebackground(dpw, dx+aw, dy, dw-aw, dh, op);
			dw = aw;
		}
		else
		{
			pw_writebackground(dpw, dx, dy, dw, dh, op);
			return;
		}
	}

	/*
	 * Handle the bottom margin.
	 * ah = available height of source image.
	 * If available height > 0 paint a margin of dh-ah height,
	 * otherwise paint the whole region.
	 */
	ah = spr->pr_height-sy;
	if(dh > ah)
	{
		if(ah > 0)
		{
			pw_writebackground(dpw, dx, dy+ah, dw, dh-ah, op);
			dh = ah;
		}
		else
		{
			pw_writebackground(dpw, dx, dy, dw, dh, op);
			return;
		}
	}

	/*
	 * Paint the image.
	 */
	pw_write(dpw, dx, dy, dw, dh, op, spr, sx, sy);
}

/*
 * pr_rect:
 *	Draws a box with op and colour as specified.
 */

void
pr_rect(pr, x, y, w, h, t, op, value)
struct pixrect *pr;
int x, y, w, h;
int t;
int op, value;
{
	int i;

	for(i = 0; i < t; i++)
	{
		pr_vector(pr, x, y, x+w-1, y, op, value);
		pr_vector(pr, x+w-1, y+1, x+w-1, y+h-2, op, value);
		pr_vector(pr, x, y+h-1, x+w-1, y+h-1, op, value);
		pr_vector(pr, x, y+1, x, y+h-2, op, value);

		x += 1;
		y += 1;
		w -= 2;
		h -= 2;

		if(w <= 0 || h <= 0)
			break;
	}
}

/*
 * pw_rect:
 *	Draws a box with op and colour as specified.
 */

void
pw_rect(pw, x, y, w, h, t, op, value)
Pixwin *pw;
int x, y, w, h;
int t;
int op, value;
{
	int i;
	Rect r;

	r.r_left = x;
	r.r_top = y;
	r.r_width = w;
	r.r_height = h;
	pw_lock(pw, &r);

	for(i = 0; i < t; i++)
	{
		pw_vector(pw, x, y, x+w-1, y, op, value);
		pw_vector(pw, x+w-1, y+1, x+w-1, y+h-2, op, value);
		pw_vector(pw, x, y+h-1, x+w-1, y+h-1, op, value);
		pw_vector(pw, x, y+1, x, y+h-2, op, value);

		x += 1;
		y += 1;
		w -= 2;
		h -= 2;

		if(w <= 0 || h <= 0)
			break;
	}

	pw_unlock(pw);
}