#include <stdio.h>
#include "rasterfile.h"
#include "basetype.h"
#include "error.h"
#include "colour.h"
#include "surface.h"
#include "bitmap.h"

static char	*
reason()
{
	extern char *sys_errlist[];
	extern int errno, sys_nerr;

	return( (errno > 0 && errno < sys_nerr) ? sys_errlist[errno]
						: "unknown reason");
} 

read_sun_raster(fname, bm_ptr)
char	*fname;
bm_t	**bm_ptr;
{
	char	*malloc();
	FILE	*fp;
	bm_t	*bm;

	if ((fp = fopen(fname, "r")) == NULL) {
		fprintf(stderr, "qrt: cannot open bitmap file %s (%s)\n", fname, reason());
		exit(1);
	}

	if (get_sun_word(fp) != RAS_MAGIC) {
		fprintf(stderr, "qrt: bitmap file %s not a sun raster\n", fname);
		exit(1);
	}

	bm = (bm_t *) malloc(sizeof(bm_t));

	if (bm == NULL) {
		fprintf(stderr, "qrt: malloc failed in read_sun_raster\n");
		exit(1);
	}

	bm->xres = get_sun_word(fp);
	bm->zres = get_sun_word(fp);
	bm->bits_per_pixel = get_sun_word(fp);
	(void) get_sun_word(fp);	/* length */
	if (get_sun_word(fp) != RT_STANDARD) {
		fprintf(stderr, "qrt: %s is not a standard bitmap\n");
		exit(1);
	}
	bm->map_type = get_sun_word(fp);
	bm->map_len =  get_sun_word(fp);

	if (bm->map_type == RT_STANDARD) {
		bm->red = malloc(sizeof(char)  * bm->map_len / 3);
		bm->green = malloc(sizeof(char)  * bm->map_len / 3);
		bm->blue = malloc(sizeof(char)  * bm->map_len / 3);
		bm->data = malloc(sizeof(char) * bm->xres * bm->zres);

		if (bm->red == NULL || bm->green == NULL || bm->blue == NULL || bm->data == NULL) {
			fprintf(stderr, "qrt: malloc failed in read_sun_raster\n");
			exit(1);
		}
		fread(bm->red, sizeof(char), bm->map_len / 3, fp);
		fread(bm->green, sizeof(char), bm->map_len / 3, fp);
		fread(bm->blue, sizeof(char), bm->map_len / 3, fp);

		fread(bm->data, sizeof(char), sizeof(char) * bm->xres * bm->zres, fp);
	} else {
		bm->data = malloc(sizeof(char) * (bm->xres + 15) / 16 * 2 * bm->zres);
		if (bm->data == NULL) {
			fprintf(stderr, "qrt: malloc failed in read_sun_raster\n");
			exit(1);
		}
		fread(bm->data, sizeof(char), sizeof(char) * (bm->xres + 15) / 16 * 2 * bm->zres, fp);
		if (big_end()) {
			rev_bits(bm->data, sizeof(char) * (bm->xres + 15) / 16 * 2 * bm->zres);
		}
	}

	*bm_ptr = bm;
}

int
get_sun_word(fp)
FILE	*fp;
{
	int	result = 0;

	result  = (getc(fp) << 24 & 0xff000000);
	result |= (getc(fp) << 16 & 0x00ff0000);
	result |= (getc(fp) <<  8 & 0x0000ff00);
	result |= (getc(fp)       & 0x000000ff);

	return(result);
}

big_end()
{
	static unsigned test_int = 0x12345678;

	return(*((char *)&test_int) == 0x12);
}

char
rev_bit(ch)
char    ch;
{
	char    tmp = 0;

	tmp = ((ch & 1) << 7);
	tmp |= ((ch & 2) << 5);
	tmp |= ((ch & 4) << 3);
	tmp |= ((ch & 8) << 1);
	tmp |= ((ch & 16) >> 1);
	tmp |= ((ch & 32) >> 3);
	tmp |= ((ch & 64) >> 5);
	tmp |= ((ch & 128) >> 7);

	return(tmp);
}

rev_bits(ptr, n)
char	*ptr;
int	n;
{
	register int	i;

	for (i = 0; i < n; i++) {
		*ptr++ = rev_bit(*ptr);
	}
}
