#ifndef lint
static char *sccsid = "@(#)output.c	1.2 (Steve Hill) 5/23/90";
#endif

/* output.c
 *
 * Routines to output images to a file.
 *
 * The file is a composed of bytes. There is a header of the following form:
 *
 * XRES(lo) XRES(hi) YRES(lo) YRES(hi)
 *
 * Then for each scan line, we have a line number (not necessarily in order)
 * followed by arrays of reds, greens and blues.
 *
 * SCANLINE(lo) SCANLINE(hi) REDS GREENS BLUES
 *
 * This format is exactly that used by Steve Koren in his QRT ray
 * tracer.
 */

#include <stdio.h>

#include "basetype.h"
#include "error.h"
#include "malloc.h"
#include "colour.h"
#include "output.h"


/* Pixels
 *
 * Allocate a line of pixels.
 */

pixel_t *
Pixels(number)
int	number;
{
	pixel_t	*pixels;

	pixels = (pixel_t *) malloc(number * sizeof(pixel_t));
	if (pixels == PixelNull)
		FatalError(__FILE__, __LINE__, "Pixels: out of memory");

	return(pixels);
}


/* PixelColour
 *
 * Calculate pixel colour from colour structure.  We shall assume
 * 24 bit colour is available - post processors can adjust the number
 * of colours if necessary.
 *
 * Returns 0 if conversion is OK, but 1 if pixel is over-exposed.
 */

int
PixelColour(pixel, colour)
pixel_t		*pixel;
colour_t	*colour;
{
	int	exposure = 0;

	if (colour->r > REAL_ONE ||
	    colour->g > REAL_ONE ||
	    colour->b > REAL_ONE)
	{
		real_t	biggest;

		exposure = 1;
		biggest = MAX(colour->r, MAX(colour->g, colour->b)) + REAL_TINY;

		colour->r /= biggest;
		colour->g /= biggest;
		colour->b /= biggest;
	}

	pixel->r = (byte_t) (colour->r * MAX_COLOURS);
	pixel->g = (byte_t) (colour->g * MAX_COLOURS);
	pixel->b = (byte_t) (colour->b * MAX_COLOURS);

	return(exposure);
}


/* OutInteger
 *
 * Output a 16-bit integer to a file (lo byte first).
 */

void
OutInteger(file, integer)
FILE	*file;
int	integer;
{
	fputc(integer & 0xff, file);
	fputc(integer >> 8, file);
}


/* OutHeader
 *
 * Generates the file header.
 */

void
OutHeader(file, x_res, y_res)
FILE	*file;
int	x_res, y_res;
{
	OutInteger(file, x_res);
	OutInteger(file, y_res);
}


/* OutScanline
 *
 * Output one scanline to a file.
 */

void
OutScanline(file, number, start, stop, colours)
FILE	*file;
int	number, start, stop;
pixel_t	*colours;
{
	int	i;

	OutInteger(file, number);

	for (i = start; i <= stop; i++)
		fputc(colours[i].r, file);

	for (i = start; i <= stop; i++)
		fputc(colours[i].g, file);

	for (i = start; i <= stop; i++)
		fputc(colours[i].b, file);
}
