[alt.sources] bitresize - filter to resize X11 bitmaps

ian@csuchico.edu (Ian Kluft) (06/01/90)

Have you ever wanted to resize an X11 bitmap?  There may be several reasons
why.

Reasons to resize a bitmap
--------------------------
* resizing a bitmap after you realize it isn't big enough for what you wanted
* removing a border from a bitmap (i.e. converted from another graphics format)
* preparation for editing an old bitmap

This problem is solved with bitresize.  It makes a copy of a bitmap in any
size.  

Usage: bitresize width height [ input-file [ output-file ] ]

How to install bitresize
------------------------
   1) unarchive the shar file
   2) type "make"
   3) read the manual page by typing
      nroff -man bitresize.1 | more

How bitresize works
-------------------
While the idea is fairly simple, bitresize is a little complicated because it
has to deal with the syntax of an X11 bitmap file, which is basically a subset
of C.  Therefore, yacc and lex were used to quickly build a parser for the
X11 bitmap format.  Therefore, to understand the source code, it helps to
understand yacc and lex.  (However, you can easily get a general idea about
it by looking at the sources.)

This is a simple data flow diagram of bitresize.

input file --(text)-->  scanner --(tokens)--> parser  --(text)--> output file
			scan.l		      bitmap.y

Most of the work is done in bitmap.y.  Additional C functions are appended to
the end of bitmap.y because, well, this was just a one-evening project and that
was one way to put it together quickly. :-)

[You'll notice that this intro was mostly taken verbatim from the README file.]

--------------------------------- cut here ---------------------------------
#
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Ian Kluft <ian@csuchico.edu> on Thu May 31 22:49:56 1990
#
# This archive contains:
#	README		bitresize.1	Makefile	bitmap.y	
#	scan.l		
#

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

echo x - README
cat >README <<'@EOF'
A quick introduction to the "Bitresize" program
by Ian Kluft
California State University, Chico

Have you ever wanted to resize an X11 bitmap?  There may be several reasons
why.  This program was made in one evening (as the sparse documentation
attests to) after one bitmap was made just a little too small.  It should
have had a larger border in order to look good as an X11 background.

Reasons to resize a bitmap
--------------------------
* resizing a bitmap after you realize it isn't big enough for what you wanted
* removing a border from a bitmap (i.e. converted from another graphics format)
* preparation for editing an old bitmap

This problem is solved with bitresize.  It makes a copy of a bitmap
in any size.  

Usage: bitresize width height [ input-file [ output-file ] ]

How to install bitresize
------------------------
   1) unarchive the shar file
   2) type "make"
   3) read the manual page by typing
      nroff -man bitresize.1 | more

How bitresize works
-------------------
While the idea is fairly simple, bitresize is a little complicated because it
has to deal with the syntax of an X11 bitmap file, which is basically a subset
of C.  Therefore, yacc and lex were used to quickly build a parser for the
X11 bitmap format.  Therefore, to understand the source code, it helps to
understand yacc and lex.  (However, you can easily get a general idea about
it by looking at the sources.)

This is a simple data flow diagram of bitresize.

input file --(text)-->  scanner --(tokens)--> parser  --(text)--> output file
			scan.l		      bitmap.y

Most of the work is done in bitmap.y.  Additional C functions are appended to
the end of bitmap.y because, well, this was just a one-evening project and that
was one way to put it together quickly.
@EOF

chmod 600 README

echo x - bitresize.1
cat >bitresize.1 <<'@EOF'
.TH BITRESIZE 1 
.SH NAME
bitresize \- resize an X11 bitmap
.SH SYNOPSIS
.B "bitresize width height"
[
.B input-file
[
.B output-file
] ]
.SH DESCRIPTION
.I Bitresize\^
is a filter program that can transform an
X11 bitmap file to an identical bitmap of a different size.
If the size (in pixels wide and high) is too
small for the previous bitmap to fit into,
.I bitresize\^
will retain as much of the upper left corner as possible.
.PP
This feature can be used to clip borders off of bitmaps.  If the
.I bitmap(1)\^
editor (by MIT and included with X11) is used to move the
image to the upper left corner,
.I bitresize\^
can be used to make a smaller copy of the bitmap without
the border.
.PP
.I Bitresize\^
can also be used to increase the size of a bitmap for
addition of more details.
.PP
For example,
.PP
.RS
bitresize 128 64 <old.bitmap.file >new.bitmap.file
.RE
.PP
resizes the X11 bitmap "old.bitmap.file"
into a bitmap called "new.bitmap.file" which will be
128 pixels wide by 64 pixels high, regardless
of the size of the old bitmap.  Also
.PP
.RS
bitresize 128 64 old.bitmap.file new.bitmap.file
.RE
.PP
does the same thing except that I/O is done directly
to the files without using the shell's I/O redirection
.PP
If no input file is given,
or if the argument
.B \-
is encountered,
.I bitresize\^
reads from the standard
input file.  This is the default action and the same works with
the standard output.
.PP
Note that no changes are made to the input file by
.I bitresize\^ .
.SH WARNING
As with any program,
.I bitresize\^
will not function correctly if the input and output
files are the same.  In such a situation, the input
bitmap file will probably be destroyed.
As usual, prevention of this error is left to the user.
.SH RETURN VALUE
Exit values are:
.RS 3
.TP 8
.B 0
Successful completion.
.PD 0
.TP
.B 1
Error condition occured.
.RE
.PD
.SH AUTHOR
.I Bitresize\^
was written by Ian Kluft at California State University, Chico.
.SH SEE ALSO
bitmap(1)
@EOF

chmod 600 bitresize.1

echo x - Makefile
cat >Makefile <<'@EOF'
#
#	Makefile for bitresize
#	by Ian Kluft
#	California State University, Chico
#	5/90
#
YFLAGS=-dv
LFLAGS=
CFLAGS=-O

SRCS=bitmap.y scan.l
OBJS=bitmap.o scan.o
SHARFILES=README bitresize.1 Makefile $(SRCS)

bitresize: $(OBJS)
	cc $(OBJS) -ll -ly -o bitresize

shar:
	shar $(SHARFILES) > bitresize.shar
@EOF

chmod 600 Makefile

echo x - bitmap.y
cat >bitmap.y <<'@EOF'
/*
 *
 *	X11 bitmap resizer
 *	by Ian Kluft
 *	California State University, Chico
 *	5/90
 *
 */

%union {
	char	*string;
	int	value;
}

%{
#include	<stdio.h>
#include	<malloc.h>

#define		PIXTOBYTE(pix)	((int)(((pix)+7)/8))

int		width,
		height,
		old_width,
		old_height;

char		*width_name,
		*height_name,
		*bitmap_name,
		*bits;		/* dynamic 2-D array w/ bytes from bitmap */

extern void	allocate_bitmap (),
		put_byte (), 
		output_bitmap ();
%}

%token <string>	ID 
%token <value>	DEFINE INTEGER HEX STATIC CHAR

%type <value>	width height allocate bitmap bytes

%start bitmap_file
%%
bitmap_file
	: width height allocate bitmap
	;

width
	: '#' DEFINE ID INTEGER
	{
		width_name = $3;
		old_width = $4;
	}
	;

height
	: '#' DEFINE ID INTEGER
	{
		height_name = $3;
		old_height = $4;
	}
	;

allocate
	: /* nothing */
	{
		allocate_bitmap ( width, height );
	}
	;

bitmap
	: STATIC CHAR ID '[' ']' '=' '{' bytes '}' ';'
	{
		bitmap_name = $3;
	}
	;

bytes
	: bytes ',' HEX
	{
		put_byte ( $3 );
		$$ = $1 + 1;
	}
	| HEX
	{
		put_byte ( $1 );
		$$ = 1;
	}
	;
%%
main ( argc, argv )
int	argc;
char	*argv[];
{
	if ( argc < 3 )
	{
		fprintf ( stderr,
			"usage: %s width height [input_file [output_file]]\n",
			argv[ 0 ] );
		exit ( 1 );
	}

	/* get new width & height from command line */
	width = atoi ( argv[ 1 ] );
	if ( width <= 0 )
	{
		fprintf ( stderr, "%s: width must be positive\n", argv[ 0 ] );
		exit ( 1 );
	}
	height = atoi ( argv[ 2 ] );
	if ( height <= 0 )
	{
		fprintf ( stderr, "%s: height must be positive\n", argv[ 0 ] );
		exit ( 1 );
	}

	/* perform file redirection if requested */
	if ( argc >= 4 && strcmp ( argv[ 3 ], "-" ) != NULL )
		if (( freopen ( argv[ 3 ], "r", stdin )) == NULL )
		{
			perror ( argv[ 0 ] );
			fprintf ( stderr, "cannot open %s for reading\n",
				argv[ 3 ] );
			exit ( 1 );
		}
	if ( argc >= 5 && strcmp ( argv[ 4 ], "-" ) != NULL )
		if (( freopen ( argv[ 4 ], "w", stdout )) == NULL )
		{
			perror ( argv[ 0 ] );
			fprintf ( stderr, "cannot open %s for writing\n",
				argv[ 4 ] );
			exit ( 1 );
		}

	/* parse through the bitmap */
	yyparse ();

	/* print the output */
	output_bitmap ();
}

void allocate_bitmap ( w, h )
int	w, h;
{
	if (( bits = calloc ( h * PIXTOBYTE ( w ), 1 )) == NULL )
	{
		fprintf ( stderr, "memory allocation error\n" );
		exit ( 1 );
	}
}

void put_byte ( b )
int	b;
{
	static int	loc = 0;

	int		over,
			down;

	/* compute position */
	down = ( int ) loc / PIXTOBYTE ( old_width );
	over = ( int ) loc % PIXTOBYTE ( old_width );

	/* if it fits in the new bitmap size, copy it */
	if ( down < height && over < PIXTOBYTE ( width )) 
		*(( char * ) bits + ( over + down * PIXTOBYTE ( width ))) =
			( char ) b;
	loc++;
}

void output_bitmap ()
{
	int	loc;

	printf ( "#define %s %d\n", width_name, width );
	printf ( "#define %s %d\n", height_name, height );
	printf ( "static char %s[] = {", bitmap_name );

	for ( loc = 0; loc < PIXTOBYTE ( width ) * height; loc++ )
	{
		static char	digits[] = "0123456789abcdef",
				hex[ 3 ] = "xx";

		/* formatting */
		if ( loc % 12 == 0 )
			printf ( "\n   " );
		else
			printf ( " " );

		/* form and print hex string */
		hex[ 0 ] = digits[ (( *( bits + loc )) & 240 ) >> 4 ];
		hex[ 1 ] = digits[ ( *( bits + loc )) & 15 ];
		printf ( "0x%2s", hex );

		/* print a comma if another byte will follow */
		if ( loc < PIXTOBYTE ( width ) * height - 1 )
			printf ( "," );
	}
	printf ( "};\n" );
}
@EOF

chmod 600 bitmap.y

echo x - scan.l
cat >scan.l <<'@EOF'
%{
/*
 *
 *	scanner for bitmap parser
 *	by Ian Kluft
 *	California State University, Chico
 *	5/90
 *
 */

#include "y.tab.h"
#include <stdio.h>
#include <string.h>

#ifdef	DEBUG
#  define	DEBUG_OUTS(fmt,str)	printf(fmt,str)
#  define	DEBUG_OUTC(out)		putchar(out)
#else !DEBUG
#  define	DEBUG_OUTS(fmt,str)
#  define	DEBUG_OUTC(out)
#endif DEBUG
%}
%%
[ \t\n]	{ DEBUG_OUTS( "%s", yytext ); }  /* skip whitespace */ 
"0x"[0-9a-fA-F]+ {
	yylval.value = strtoul ( yytext + 2, ( char ** ) NULL, 16 );
	DEBUG_OUTS( "%s", yytext );
	return ( HEX ); }
[0-9]+ {
	yylval.value = atoi ( yytext );
	DEBUG_OUTS( "%s", yytext );
	return ( INTEGER ); }
"define" { DEBUG_OUTS( "%s", yytext ); return ( DEFINE ); }
"static" { DEBUG_OUTS( "%s", yytext ); return ( STATIC ); }
"char"	{ DEBUG_OUTS( "%s", yytext ); return ( CHAR ); }
[a-zA-Z_][a-zA-Z0-9_]* {
	yylval.string = strdup ( yytext );
	DEBUG_OUTS( "%s", yytext );
	return ( ID ); }
"/*"	{	/* skip comments */
	int	done,
		c;

	DEBUG_OUTS ( "%s", yytext );
	done = 0;
	while ( ! done )
	{
		c = input (); DEBUG_OUTC ( c );
		if ( c == '*' )
		{
			c = input (); DEBUG_OUTC ( c );
			done = ( c == '/' );
		}
	}
}
.	{ DEBUG_OUTS( "%s", yytext ); return ( yytext[0] ); }  /* everything else */
%%
@EOF

chmod 600 scan.l

exit 0

--------------------------- cut out signature here ---------------------------

--
Ian Kluft               ----------------------------- # Sometimes all it takes
grad student, CSU Chico          \ |--*--| /          # to make someone a real
member ACM, UPE, AOPA     C - 172  /\___/\  Skyhawk   # flying enthusiast is...
PP-SEL                            o   o   o           #      one flight