/*
 * cmap.c
 *
 * Copyright (C) 1993, 1994 Evan Harris
 *
 * Permission is granted to freely redistribute and modify this code,
 * providing the author(s) get credit for having written it.
 */

#include "seejpeg.h"
#include <vga.h>


#define HASHTABLESIZE 1024
#define CMAPSIZE 256

#define NOENTRY 0x80000000

static unsigned long hashtable[HASHTABLESIZE];

static unsigned long last_colour;
static int next_cmap_entry;

void
translate_init()
{
    int i;

    last_colour = 0;
    next_cmap_entry = 0;

    for (i = 0; i < HASHTABLESIZE; i++) {
	hashtable[i] = NOENTRY;
    }
}


static JSAMPLE
lookup_colour(JSAMPLE r, JSAMPLE g, JSAMPLE b)
{
    unsigned long colour;
    int key;

    /*
     * VGA colours are 18 bit.
     */
    r >>= 2;
    g >>= 2;
    b >>= 2;

    colour = ((r << 20) | (g << 14) | (b << 8));
    if (colour == (last_colour & 0xffffff00)) {
	return (last_colour & 0xff);
    }

    /*
     * We probably need a better hash function, but this is better than
     * nothing
     */
    key = ((r << 4) ^ (g << 2) ^ b);
  
    while (hashtable[key] != NOENTRY
	   && colour != (hashtable[key] & 0xffffff00)) {
	if (++key == HASHTABLESIZE) {
	    key = 0;
	}
    }
    if (hashtable[key] == NOENTRY) {
	if (next_cmap_entry == CMAPSIZE) {
	    error_exit("Colour map full");
	}
	hashtable[key] = (colour | next_cmap_entry);
	vga_setpalette(next_cmap_entry, r, g, b);
	next_cmap_entry++;
    }
    last_colour = hashtable[key];

    return (last_colour & 0xff);
}


void
translate_row(int width, JSAMPARRAY rgb_row, JSAMPARRAY cmap_row)
{
    JSAMPROW inr, ing, inb, out;
    int i;

    /*
     * Assume there are three components in the input and one in the output
     */
    inr = rgb_row[0];
    ing = rgb_row[1];
    inb = rgb_row[2];
    out = cmap_row[0];
  
    for (i = 0; i < width; i++) {
	*out++ = lookup_colour(*inr++, *ing++, *inb++);
    }
}
