/* wasper - copyright 1990, 1991 by Steven Reiz
 * compute the difference between two SRGR files of same size
 * see formats/srgr.doc for a description of the SRGR format
 * 30/12/90 - 3/1/91, 30/6/91
 */

#include <fcntl.h>
extern void *malloc();

int fd[3];
long xsz[2], ysz[2];
int er_pic=0;


main(argc, argv)
int argc;
char **argv;
{
    int i;
    long t;

    if (argc<3 || argc>4) {
        printf("usage: wasper srgr-file-1 srgr-file-2 [error-picture-file]\n");
        exit(1);
    }
    if (argc>3)
	er_pic=1;
    for (i=1; i<=2; ++i) {
        if ((fd[i-1]=open(argv[i], O_RDONLY))<0) {
            perror(argv[i]);
            exit(1);
        }
    }
    if (er_pic) {
	if ((fd[2]=open(argv[3], O_WRONLY|O_CREAT|O_TRUNC))<0) {
	    perror(argv[3]);
	    exit(1);
	}
    }
    for (i=0; i<=1; ++i) {
        cread(fd[i], &t, 4);
        if (t!=(('S'<<24)|('R'<<16)|('G'<<8)|'R')) {
            printf("%s is no SRGR file!\n", argv[i+1]);
            exit(1);
        }
        cread(fd[i], &xsz[i], 4);
        cread(fd[i], &ysz[i], 4);
        printf("%s: SRGR %ldx%ld\n", argv[i+1], xsz[i], ysz[i]);
    }
    if (xsz[0]!=xsz[1] || ysz[0]!=ysz[1]) {
        printf("the two input pictures should have exactly the same size!\n");
        exit(1);
    }
    if (er_pic) {
	t=('S'<<24)|('R'<<16)|('G'<<8)|'R';
	cwrite(fd[2], &t, 4);
	cwrite(fd[2], &xsz[0], 4);
	cwrite(fd[2], &ysz[0], 4);
    }
    compute_errs();
    exit(0);
}


#define BUFSZ 32760
long sqr[16];
long error, error2;
unsigned char *buf1, *buf2, *bufo;
int thischunk;

compute_errs()
{
    long todo;
    short i;

    for (i=0; i<16; ++i)
        sqr[i]=i*i;
    if (!(buf1=malloc(BUFSZ))) {
        printf("not enough memory\n");
        exit(1);
    }
    if (!(buf2=malloc(BUFSZ))) {
        printf("not enough memory\n");
        exit(1);
    }
    if (er_pic && !(bufo=malloc(BUFSZ))) {
	printf("not enough memory\n");
	exit(1);
    }
    error=0;
    error2=0;
    todo=xsz[0]*ysz[0]*2;
    while (todo>0) {
        thischunk=BUFSZ;
        if (thischunk>todo)
            thischunk=todo;
        todo-=thischunk;
        cread(fd[0], buf1, thischunk);
        cread(fd[1], buf2, thischunk);
	if (er_pic) {
		do_er_pic();
		cwrite(fd[2], bufo, thischunk);
	} else
		do_er();
		
    }
    printf("error: %ld, error2: %ld\n", error, error2);
}


do_er()
{
	unsigned char *p, *q;
	long e, e2, n, d;
	unsigned long c1, c2;
	
	p=buf1;
	q=buf2;
	e=e2=0;
	n=thischunk-1;
        do {
            c1= *p++;
            c2= *q++;
            if ((d=(c1&0x0f)-(c2&0x0f))<0)
                d= -d;
            e+=d;
            e2+=sqr[d];
            if ((d=(c1>>4)-(c2>>4))<0)
                d= -d;
            e+=d;
            e2+=sqr[d];
        } while (--n>=0);
	error+=e;
	error2+=e2;
}


do_er_pic()
{
	unsigned char *p, *q, *r;
	long e, e2, n, d;
	unsigned long c1, c2;
	
	p=buf1;
	q=buf2;
	r=bufo;
	e=e2=0;
	n=thischunk-1;
        do {
            c1= *p++;
            c2= *q++;
            if ((d=(c1&0x0f)-(c2&0x0f))<0)
                d= -d;
	    if (d==1) {
		*r=0x08;
		++e;
		++e2;
	    } else if (d) {
		*r=0x0f;
	        e+=d;
                e2+=sqr[d];
	    } else
		*r=0x00;
            if ((d=(c1>>4)-(c2>>4))<0)
                d= -d;
	    if (d==1) {
		*r++ |=0x80;
		++e;
		++e2;
	    } else if (d) {
		*r++ |=0xf0;
	        e+=d;
                e2+=sqr[d];
	    } else
		++r;
        } while (--n>=0);
	error+=e;
	error2+=e2;
}


cread(fde, buf, len)
int fde;
void *buf;
int len;
{
    int r;

    r=read(fde, buf, len);
    if (r<0) {
        perror("read");
        exit(1);
    } else if (r!=len) {
        printf("read: unexpected EOF\n");
        exit(1);
    }
}


cwrite(fde, buf, len)
int fde;
void *buf;
int len;
{
    if (write(fde, buf, len)!=len) {
        perror("write");
        exit(1);
    }
}
