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

#include <jinclude.h>
#include "shared.h"


#define HASHTABLESIZE 1024
#define CMAPSIZE 256

static unsigned long hashtable[HASHTABLESIZE];


void
translate_init()
{
  int i;

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


static JSAMPLE
lookup_colour(JSAMPLE r, JSAMPLE g, JSAMPLE b)
{
  static unsigned long last_colour = 0;
  static int next_cmap_entry = 1;
  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 == 0) {
    return 0;
  }
  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] != 0 && colour != (hashtable[key] & 0xffffff00)) {
    if (++key == HASHTABLESIZE) {
      key = 0;
    }
  }
  if (hashtable[key] == 0) {
    if (next_cmap_entry == CMAPSIZE) {
      printf("Colour map full\n");
      exit(-1);
    }
    hashtable[key] = (colour | next_cmap_entry);
    image_palette[next_cmap_entry * 3] = r << 2;
    image_palette[next_cmap_entry * 3 + 1] = g << 2;
    image_palette[next_cmap_entry * 3 + 2] = b << 2;
    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++);
  }
}
