/* +-------------------------------------------------------------------+ */
/* | Copyright 1992, David Koblas.                                     | */
/* |   Permission to use, copy, modify, and distribute this software   | */
/* |   and its documentation for any purpose and without fee is hereby | */
/* |   granted, provided that the above copyright notice appear in all | */
/* |   copies and that both that copyright notice and this permission  | */
/* |   notice appear in supporting documentation.  This software is    | */
/* |   provided "as is" without express or implied warranty.           | */
/* +-------------------------------------------------------------------+ */

#include "pnm.h"
#include "pgm.h"
#include "ppm.h"

static gray	**alpha = NULL;
static int	alphaCols, alphaRows;
static xelval	alphaMax;
static pixel	**image = NULL;
static int	imageCols, imageRows, imageType;
static xelval	imageMax;
static int	InvertFlag = 0;

static char	*usage = 
	"[-invert] [-xoff N] [-yoff N] [-alpha file] overlay [image] [output]";

main(argc, argv) 
int	argc;
char	*argv[];
{
	int	xoff = 0, yoff = 0;
	FILE	*ifp, *ofp, *fp;
	int	argn = 1;

	pnm_init(&argc, argv);

	while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
		if (pm_keymatch(argv[argn], "-xoff", 2)) {
			if (argn == argc || 
			    sscanf(argv[++argn], "%d", &xoff) != 1)
				pm_usage(usage);
		} else if (pm_keymatch(argv[argn], "-yoff", 2)) {
			if (argn == argc || 
			    sscanf(argv[++argn], "%d", &yoff) != 1)
				pm_usage(usage);
		} else if (pm_keymatch(argv[argn], "-alpha", 2)) {
			if (argn == argc || alpha != NULL) 
				pm_usage(usage);
			
			fp = pm_openr(argv[++argn]);
			alpha = pgm_readpgm(fp, &alphaCols, 
						&alphaRows, &alphaMax);
			pm_close(fp);
		} else if (pm_keymatch(argv[argn], "-invert", 2)) {
			InvertFlag = 1;
		} else {
			pm_usage(usage);
		}
		argn++;
	}

	/*
	**  Read the overlay file
	*/
	if (argc == argn)
		pm_usage(usage);
	
	fp = pm_openr(argv[argn++]);
	image = pnm_readpnm(fp, &imageCols, &imageRows, &imageMax, &imageType);
	pm_close(fp);

	/*
	**  If there is an alphamap check to make sure it is the
	**    same size as the image.
	*/
	if (alpha != NULL && (imageCols!=alphaCols || imageRows!=alphaRows)) 
		pm_error("Alpha map and Image are not the same size");

	/*
	**  Now get the data file
	*/
	if (argc != argn) 
		ifp = pm_openr(argv[argn++]);
	else 
		ifp = stdin;

	/*
	**  And the output file
	*/
	if (argc != argn) 
		ofp = pm_openw(argv[argn++]);
	else 
		ofp = stdout;

	/*
	**  Composite the images together
	*/
	composite(xoff, yoff, ifp, ofp);

	pm_close(ifp);
	pm_close(ofp);
}

composite(xoff, yoff, ifp, ofp)
int	xoff, yoff;
FILE	*ifp, *ofp;
{
	int	x, y, x0, y0;
	int	r,g,b;
	xelval	v, maxv, omaxv;
	xel	*pixels;
	double	f;
	int	rows, cols, type, otype;

	pnm_readpnminit(ifp, &cols, &rows, &maxv, &type);

	pixels = pnm_allocrow(cols);

	pnm_writepnminit(ofp, cols, rows, maxv, type, 0);

	/*
	**  Convert overlay image to common type & max
	*/
	otype = (imageType < type) ? type : imageType;
	omaxv = (imageMax  < maxv) ? maxv : imageMax;

	if (imageType != otype || imageMax != omaxv) {
		pnm_promoteformat(image, imageCols, imageRows, 
				imageMax, imageType, omaxv, otype);
		imageType = otype;
		imageMax  = omaxv;
	}

	for (y = 0; y < rows; y++) {
		/*
		**  Read a row and convert it to the output type
		*/
		pnm_readpnmrow(ifp, pixels, cols, maxv, type);

		if (type != otype || maxv != omaxv)
			pnm_promoteformatrow(pixels, cols, maxv, 
						type, omaxv, otype);

		/*
		**  Now overlay the overlay with alpha (if defined)
		*/
		for (x = 0; x < cols; x++) {
			x0 = x - xoff;
			y0 = y - yoff;

			if (x0 < 0 || x0 >= imageCols)
				continue;
			if (y0 < 0 || y0 >= imageRows)
				continue;

			if (alpha == NULL) {
				f = 1.0;
			} else {
				f = (double)alpha[y0][x0] / (double)alphaMax;
				if (InvertFlag) 
					f = 1.0 - f;
			}

			r = PPM_GETR(pixels[x])     * (1.0 - f) + 
			    PPM_GETR(image[y0][x0]) * f;
			g = PPM_GETG(pixels[x])     * (1.0 - f) + 
			    PPM_GETG(image[y0][x0]) * f;
			b = PPM_GETB(pixels[x])     * (1.0 - f) + 
			    PPM_GETB(image[y0][x0]) * f;

			PPM_ASSIGN(pixels[x], r, g, b);
		}

		pnm_writepnmrow(ofp, pixels, cols, maxv, otype, 0);
	}

	pnm_freerow(pixels);
}
