[unix-pc.sources] MacPaint.pic -> PC7300 display

clb) (01/24/88)

	This program "mac73" reads MacPaint files and displays them on
	the unixpc (PC7300) console. This routine is based on the program
	"showPaint" by Rick Kimball (flnexus!kimbal!rick) which appeared
	recently on the net.  However, this routine is completely rewritten
	and shares nothing in actual code.

	Functional differences:
		preserves aspect ratio (circles are circles, not ellipses.)
		steps through entire image, not just top.

	Structural differences:
		expects to be run in 80x24 window, doesn't create new window.
		displays image scan by scan, direct from disk: no buffering.

	Creation is by ...

cc mac73.c -s -o mac73

	Execution is by ...

$ mac73 McPaint.pic

	where "McPaint.pic" is the MacPaint file.  It will locate the data
	fork, unpack and invert the picture, then display the top 288 lines
	centered horizonally. The program will wait for a "newline",
	and then shift the image upward, displaying a center slice and
	wait for a newline. When the user responds, the program moves
	the image upward to show the bottom of the picture and exits.

	Note that this program doesn't create a new window, and expects
	a 80x24 "NOBORDER" console set-up (720x288 pixels). It will not
	work properly if run from "ua". The aspect ratio algorithm is
	simply to skip every third line, and seems to give reasonable
	results for scanned photographs but may not for all "pix".

	Send questions/comments to ... ihnp4!killer!loci!clb


##---------Cut Here-----##

#include <stdio.h>
#include <fcntl.h>
#include <sys/window.h>

	/* MacPaint Picture defines */
#define MAC_WIDTH 576			/* 576 pixels	*/
#define ROW_BYTES 72			/* 576 pixels wide / 8	*/
#define NO_OF_LINES 720			/* 720 line	*/
#define MAX_MACPAINT_SIZE	51840L	/* ROW_BYTES * NO_OF_LINES */

#define	wbfr	scan
char	scan[1024];
struct urdata	ur_image =
	{	0, 72, 0, 0, 0, 0, 72, 0, 576, 1, SRCSRC, DSTSRC, 0 };
struct urdata	ur_top =
	{	0, 72, 0, 72, 72, 96, 72, 0, 576, 192, SRCSRC, DSTSRC, 0 };
struct utdata	slk_text[] =
{
	{	WTXTSLK1, " Press <RETURN> to continue ..." },
	{	WTXTSLK1, "" }
};

main(argc, argv)
char *argv[];
{
	int	fd;

	if(argc < 2)
		exit(0);
	if((fd=open(argv[1], O_RDONLY)) < 0)
	{
		printf("%s: can't open MacPaint file\n", argv[0]);
		exit(1);
	}
	printf("\033[2J\033[1;1H");	/* clear screen, home cursor */
	ioctl(0, WIOCSETTEXT, &slk_text[0]);
	UnPackPaint(fd);
	ioctl(0, WIOCSETTEXT, &slk_text[1]);
}

UnPackPaint(fd)
{
	int		i, j;

	if((read(fd, wbfr, 512)) != 512)
		exit(1);
	if((strncmp(&wbfr[65], "PNTGMPNT", 8)) == 0)
		lseek(fd, 128L, 1);
	ur_image.ur_srcbase = (unsigned short *)scan;
	for(i=0; i<432; i++)
	{
		rd_scan(fd, ROW_BYTES, scan);
		if(i%3 == 0)
			continue;
		rev_bits(scan, ROW_BYTES);
		ioctl(0, WIOCRASTOP, &ur_image);
		ur_image.ur_dsty++;
	}
	for(j=0; j<2; j++)
	{
		gets(wbfr);
		ioctl(0, WIOCRASTOP, &ur_top);
		ur_image.ur_dsty = 192;
		for(i=0; i<144; i++)
		{
			rd_scan(fd, ROW_BYTES, scan);
			if(i%3 == 0)
				continue;
			rev_bits(scan, ROW_BYTES);
			ioctl(0, WIOCRASTOP, &ur_image);
			ur_image.ur_dsty++;
		}
	}
	close(fd);
}

#define BIT7	0x80

rd_scan(fd, cnt, dst_p)
char	*dst_p;
{
	int		nbytes;
	unsigned char	bit7;
	char		c_data, r_data;

	if(cnt <= 0)	return(0);

	bit7 = BIT7;
	while(cnt > 0)
	{
		if(read(fd, &c_data, 1) != 1)
			return(-1);
		if(c_data & bit7)	/* High bit set ? */
		{
			nbytes = abs(c_data); 
			cnt -= ++nbytes;
			if(read(fd, &r_data, 1) != 1)
				return(-1);
			while(nbytes--)
				*dst_p++ = r_data;	/* repeat src byte */
		} else {		/* It is a normal zero based counter */
			nbytes = c_data;
			cnt -= ++nbytes;
			if(read(fd, dst_p, nbytes) < 1)
				return(-1);
			dst_p += nbytes;
		}
	}
	return(0);
}

rev_bits(srcPtr, nbytes)
long	*srcPtr;
{
	register	n_data, o_data;
	int		hi_bits, bitCnt;

	if(nbytes < 0)
		return(0);
	nbytes >>= 2;
	hi_bits = 0x00010001;          /* Let's deal with the short as longs */
	while(nbytes--)
	{
		n_data = *srcPtr;
		o_data = 0;
		for(bitCnt=0; bitCnt<15; bitCnt++)
		{
			o_data |= n_data & hi_bits; /* See if this bit is on */
			n_data >>= 1;
			o_data <<= 1;
		}
		o_data |= n_data & hi_bits;
		*srcPtr++ = o_data ^ -1; /* -1 for screen, 0 for printer */
	}
	return(0);
}