#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#define NAME "alphaconv"
#define RNG(x) ((x)>res1?res1:((x)<0?0:(x)))

void fail(char * s) {
	fprintf(stderr,s,NAME);
	exit(1);
}

int checkmagic(FILE *f) {
	int c;
	if (getc(f) != 'P' || getc(f) != '6')
		return 0;
	/* The code below is because ghostscript inserts a non-standard
	   comment after the magic number */
	while(isspace(c=getc(f))); 
	if (c=='#')
	       while(getc(f)!='\n');
	else
		ungetc(c,f);
	return 1;	
}
main(int argc, char *argv[]) {
	int width1, height1, width2, height2, res1, res2;
	long length;
	int red_b,green_b,blue_b, red_w, green_w, blue_w;
	int red, green, blue;
	int alpha;
	FILE *inb, *inw, *rgb, *al;
	if (argc !=5)
		fail("Usage: %s <black-bg infile> <white-bg infile> <rgb outfile> <alpha outfile>\n");
	if (!(inb=fopen(argv[1],"rb")) || !(inw=fopen(argv[2],"rb")))
		fail("\n%s: Unable to open input file\n");
	if (!checkmagic(inb) || !checkmagic(inw))
		fail("\n%s: Unsupported input file format\n");
	if ((fscanf(inb,"%d %d %d", &width1, &height1, &res1)!=3) 
	 || (fscanf(inw,"%d %d %d", &width2, &height2, &res2)!=3)
	 || !isspace(getc(inb)) || !isspace(getc(inw))) 
		fail("\n%s: Unsupported input file format\n");
	if ( width1 != width2 || height1 != height2)
		fail("\n%s: Input images are different shapes\n");
	if ( res1 != res2)
		fail("\n%s: Files have different colour depths\n");
	if ( res1 >255 || width1 <1 || height1 < 1 || res1 <1 )
		fail("\n%s: Unsupported input file format\n");
	if (!(rgb=fopen(argv[3],"wb")))
		fail("\n%s: Unable to open output file\n");
	if (!(al=fopen(argv[4],"wb")))
		fclose(rgb), fail("\n%s: Unable to open output file\n");
	if (fprintf(rgb,"P6\n%d %d\n%d\n",width1,height1,res1)<0 
	 || fprintf(al, "P5\n%d %d\n%d\n",width1,height1,res1)<0) 
		fclose(rgb), fclose(al), fail("\n%s: File write error");
	length=(long)width1*(long)height1;
	while (length--) {
		if((red_b=getc(inb))==EOF || (green_b=getc(inb))==EOF
		 || (blue_b=getc(inb)) == EOF || (red_w=getc(inw))==EOF
		 || (green_w=getc(inw))==EOF  || (blue_w=getc(inw))==EOF)
			fclose(rgb), fclose(al), fail("\n%s: File read error\n");
		alpha = RNG(res1+(red_b+green_b+blue_b-red_w-green_w-blue_w)/3);
		if (alpha==0) 
			/* If there's no alpha, make it white */
			red=green=blue=res1;
		else {
			red  =RNG(((long)red_b  *(long)res1)/(long)alpha);
			green=RNG(((long)green_b*(long)res1)/(long)alpha);
			blue =RNG(((long)blue_b *(long)res1)/(long)alpha);
		}
		if(fputc(alpha,al) == EOF || fputc(red,rgb) == EOF
		 || fputc(green,rgb) == EOF || fputc(blue,rgb) == EOF)
			fclose(rgb), fclose(al), fail("\n%s: File write error\n");
	}
	if (fclose(rgb)) 
		fclose (al), fail("\n%s: File close error\n");
	if (fclose(al))
		fail("\n%s: File close error\n");
	fclose(inb);
	fclose(inw);	
	exit(0);
}
