V10/cmd/imscan/imscan.c
#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;
}
}