Subject: doubling the size of a bitmap

From: "Ross Paterson" <[email-masked]>
Date: Thu, 23 Jul 1992 11:28:19 BST

Greetings,

Dissatisfied with the appearance of 24x24 fonts on a 300 dpi printer,
and too cheap to pay for a 48x48 font, I wrote the following function
to double both dimensions of a bitmap, with a bit of smoothing.
It is pretty dumb, examining only a small area around each point, and
you can certainly do much better by hand, but it does a moderate job.
It does worst on edges that are nearly vertical or horizontal.  Also,
it makes the bitmaps about 1% darker.
--
Ross Paterson <[email-masked]>
Department of Computing, Imperial College, London SW7
----------------------------- cut here ------------------------------
/*
 * Double the size of a bitmap, with a bit of local smoothing.
 *
 * A bitmap is stored in row-major order, 8 bits per byte, top bit first.
 *
 * Ross Paterson <[email-masked]>
 */

typedef	int	bool;
#define	TRUE	1
#define	FALSE	0

static	void	set();
static	bool	get();

void
double_bm(in, w, h, out)
	char	*in;	/* input bitmap: w*h bits */
	int	w;	/* width of input bitmap */
	int	h;	/* height of input bitmap */
	char	*out;	/* output bitmap: 2*w*2*h bits */
{
	int	x, y;
	bool	c;

	for (y = 0; y < h; y++)
	    for (x = 0; x < w; x++) {
		c = get(in, w, h, x, y);
		set(out, w*2, x*2, y*2, c);
		set(out, w*2, x*2, y*2+1, c);
		set(out, w*2, x*2+1, y*2, c);
		set(out, w*2, x*2+1, y*2+1, c);
	    }
	for (y = 0; y < h; y++)
	    for (x = 0; x < w; x++) {
		c = get(in, w, h, x, y);
		if (c != get(in, w, h, x-1, y)) {
			if (c != get(in, w, h, x-1, y-1) &&
			    c != get(in, w, h, x, y-1)) {
				/*
				 *	OOX
				 *	OX?  -> move NW bit to right
				 *	???
				 */
				if (c == get(in, w, h, x+1, y-1)) {
					set(out, w*2, x*2, y*2, ! c);
					if (c)
						set(out, w*2, x*2+2, y*2, c);
				}
				/*
				 *	OO?
				 *	OX?  -> move NW bit down
				 *	X??
				 */
				if (c == get(in, w, h, x-1, y+1)) {
					set(out, w*2, x*2, y*2, ! c);
					if (c)
						set(out, w*2, x*2, y*2+2, c);
				}
			}
			if (c != get(in, w, h, x-1, y+1) &&
			    c != get(in, w, h, x, y+1)) {
				/*
				 *	???
				 *	OX?  -> move SW bit to right
				 *	OOX
				 */
				if (c == get(in, w, h, x+1, y+1)) {
					set(out, w*2, x*2, y*2+1, ! c);
					if (c)
						set(out, w*2, x*2+2, y*2+1, c);
				}
				/*
				 *	X??
				 *	OX?  -> move SW bit up
				 *	OO?
				 */
				if (c == get(in, w, h, x-1, y-1)) {
					set(out, w*2, x*2, y*2+1, ! c);
					if (c)
						set(out, w*2, x*2, y*2-1, c);
				}
			}
		}
	    }
#ifdef	DEBUG
	for (y = 0; y < h*2; y++) {
		for (x = 0; x < w*2; x++)
			putchar(get(out, w*2, h*2, x, y) ? '%' : ' ');
		putchar('\n');
	}
#endif
}

static bool
get(arr, w, h, x, y)
	char	*arr;
	int	w;
	int	h;
	int	x;
	int	y;
{
	int	pos;

	if (x < 0 || x >= w || y < 0 || y >= h)
		return FALSE;
	pos = y*w + x;
	return (arr[pos/8] >> (7 - pos%8)) & 01;
}

static void
set(arr, w, x, y, value)
	char	*arr;
	int	w;
	int	x;
	int	y;
	bool	value;
{
	int	pos;

	pos = y*w + x;
	if (value)
		arr[pos/8] |= 1 << (7 - pos%8);
	else
		arr[pos/8] &= ~(1 << (7 - pos%8));
}