V10/cmd/imscan/imscan.c

Compare this file to the similar file:
Show the results in this format:

#include "I_lut.h"

#define	MAX	4096		/* max no of 16bit words per read */

/*
	set, on the scanner console:
	off	normalization		(N menu) (press 'N' <enter>)
	off	log lookup tables	(N menu)
	ON	log circuit		(N menu)
	off	historical calibration	(H menu)
*/

#define	IMRESET	(('i'<<8)|1)
#define	IMWAIT	(('i'<<8)|2)

int printf;		/* andrew doesn't like printf */

int SCALE = 4;		/* reduction factor of 4 */
int LENS  = 0;		/* defaults to 8.5 inch lens */
int TRANS = 0;		/* reflection scanning is default */
int ALLOC = 0;		/* pre-allocate memory */
int correct = 0;

Usage()
{
	print("usage: imscan [-sN] [-lN] [-t] [-r] file\n");
	print("\t-sN	reduction factor N:[1-9] (default is 4)\n");
	print("\t-lN	N=5 for 5 inch lens; N=8 for 8.5 inch lens\n");
	print("\t	5=754 dpi, 8=480 dpi (the default is 8)\n");
	print("\t-t	transmission (glass plate)\n");
	print("\t-r	reflection   (metal plate - default)\n");
	print("\t-n	apply image correction\n");
	print("\t-aN	pre-allocate for an Nbyte (N=wxh) image\n");
	exit(1);
}

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

	while (argc > 1 && argv[1][0] == '-')
	{	switch (argv[1][1]) {
		case 's':	if (argv[1][2] < '1' || argv[1][2] > '9')
					Usage();
				SCALE = argv[1][2] - '0';
				break;
		case 'l':	if (argv[1][2] != '5' && argv[1][2] != '8')
					Usage();
				LENS = (argv[1][2] == '5');
				break;
		case 't':	TRANS = 1; break;
		case 'r':	TRANS = 0; break;
		case 'n':	correct = 1-correct; break;
		case 'a':	if (argv[1][2] < '1' || argv[1][2] > '9')
					Usage();
				ALLOC = atoi(&argv[1][2]);
				break;
		default :	Usage();
		}
		argc--; argv++;
	}
	if (argc < 2)
		Usage();

	print("reduction factor %d, ", SCALE);
	print("%s lens, ", (LENS)?"5 inch":"8.5 inch");
	print("%s scan, ", (TRANS)?"transmission":"reflection");
	print("image file: %s\n", argv[1]);

	if ((fd = open("/dev/im0", 2)) < 0)
	{	perror("/dev/im0");
		exit(1);
	}
	if ((ofd = creat(argv[1], 0666)) < 0)
	{	perror(argv[1]);
		exit(1);
	}
	seticonfig(fd);
	setmodes(fd);
	scan(fd, ofd);

	exit(0);
}

scan(fd, ofd)
{	unsigned short buf1[32], buf2[32];
	int tpix, mode, npix, nlin, spl, NLINES;
	char *im, *sim, *malloc();
	register char *pim;
	register int n, tlin;

	if (ALLOC)
		pim = im = (char *) malloc(ALLOC);

	print("scan preliminaries\n");
	buf1[0] = 0x100;		/* manual swab */
	buf1[1] = 0x400;		/* SCAN1START swabbed */

	if (write(fd, buf1, 4) != 4)	{ perror("write"); return; }
	if (ioctl(fd, IMWAIT) < 0)	{ perror("imwait1"); return; }
	if (read(fd,  buf1, 12) != 12)	{ perror("read"); return; }

	swab(&buf1[1], buf2, 10);

	npix = (int) buf2[2];
	nlin = (int) buf2[3];
	mode = (int) buf2[4];

	buf1[0] = 5;
	buf1[1] = 5;			/* SCAN2START */
	buf1[2] = SCALE*256;		/* XSCALE */
	buf1[3] = SCALE*256;		/* YSCALE */
	buf1[4] = 0;			/* no run length encoding */
	buf1[5] = 0;			/* no pixel replication   */
	swab(buf1, buf2, 12);

	if (write(fd, buf2, 12) != 12)	{ perror("scan2 write"); return; }
	if (read(fd,  buf1, 12) != 12)	{ perror("scan2 read");  return; }

	swab(&buf1[1], buf2, 10);

	tpix = (int) buf2[2];
	tlin = (int) buf2[3];
	mode = (int) buf2[4];

	spl  = (tpix+15)/16;		/* line size, in 16-bit words */
	spl *= 8;			/* one byte per pixel  */
	NLINES = MAX/spl;
	n    = (NLINES*spl+3)*2;	/* no of bytes to read per chunk */

	print("%dx%d -> %dx%d pixel\n", npix, nlin, 2*spl, tlin);
	if (mode != 2) { print("error: not in b&w mode\n"); return; }
	if (NLINES<=0) { print("error: line too wide\n"); return; }

	if (ALLOC == 0)
		pim = im = (char *) malloc(npix*tlin);	/* was n*tlin */
	else
	{	if (npix*tlin > ALLOC)
		{	print("error: not enough memory allocated %d != %d*%d\n",
				ALLOC, n, tlin);
			return;
		}
	}

	buf1[0] = 2;
	buf1[1] = 7;
	buf1[2] = NLINES*spl;
	swab(buf1, buf2, 6);

	for (tlin = 0; ; tlin++)
	{	if (write(fd, buf2, 6) != 6) { perror("!reset scanner"); break; }
		if (read(fd, pim, n) != n) break;
		pim += n;
	}

	header(ofd, 2*spl, tlin*NLINES);
	if (correct)
	{	register int j;
		print("image correction...\n");
		pim = im+6;
		if (TRANS)
			for (j = tlin*n; j > 0; j--, pim++)
				*pim = 255 - *pim;
		else
			for (j = tlin*n; j > 0; j--, pim++)
				*pim = cor_refl[*pim];
	}
	sim = im+6;
	while (tlin-- > 0)
	{	write(ofd, sim, n-6);
		sim += n;
	}
	return;
}

header(ofd, a, b)
{
	Fprint(ofd, "TYPE=dump\nWINDOW=0 0 %d %d\nNCHAN=1\n", a, b);
	Fprint(ofd, "COMMAND=imscan -s%d ", SCALE);
	if (!correct) Fprint(ofd, "-n ");
	Fprint(ofd, "-l%d -%c\n\n", (LENS)?5:8, (TRANS)?'t':'r');
	Fflush(ofd);
}

seticonfig(fd)
{	unsigned short buf1[7], buf2[7];

	buf1[0] = 6;
	buf1[1] = 1;	/* SETIMAGECONFIG */
	buf1[2] = 4;	/* nparams */
	buf1[3] = 0;	/* line art*/
	buf1[4] = 0;	/* bw */
	buf1[5] = 24;	/* colour */
	buf1[6] = 40;	/* speed (40-500) 80 is about as fast as you can go */
	swab(buf1, buf2, 14);
	if (write(fd, buf2, 14) != 14)
	{	perror("seticonfig write");
		return;
	}
	if (read(fd, buf1, 6) != 6)
	{	perror("seticonfig read");
		return;
	}
}

setmodes(fd)
{	unsigned short buf1[7], buf2[7];

	buf1[0] = 6;
	buf1[1] = 21;	/* SETMODES */
	buf1[2] = LENS;	/* 1 = 5 inch, 0 = 8.5 inch lens */
	buf1[3] = 0;	/* line art (0=cont tone, 1=line art) */
	buf1[4] = TRANS;	/* 0=reflection, 1=transmission */
	buf1[5] = 1;	/* b/w */
	buf1[6] = 1;	/* autoscan */
	swab(buf1, buf2, 14);
	if (write(fd, buf2, 14) != 14)
	{	perror("setmodes write");
		return;
	}
	if (read(fd, buf1, 6) != 6)
	{	perror("setmodes read");
		return;
	}
}