/* Hey, emacs, this is -*- C -*- code.  */

/* dither.c - reduce the size and color composition of a map

Copyright (C) 1992 D P Gymer

This is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
   Foundation; either version 2 of the License, or (at your option) any later
   version.

This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.  */

/* $Id: dither.c,v 0.3.2.0 1992/06/11 22:30:07 dpg Alpha dpg $ */

#include "view.h"

/* Reduce the size of the palette.  BUGS - not really written yet.  */
static int
map_colors (COLOR *map, PALETTE **pal, int colors, int req_c)
{
  colors = 0;
  while (*pal)
    {
      map[(*pal)->number] = (*pal)->number;
      pal = &(*pal)->next;
      ++colors;
    }
  return colors;
}

/* Dither a map.  The function should return 0 if all goes according plan, 1
   otherwise.  We actually plot the map here as well, since it would be
   inefficient to build up a new map just to plot it straight away and free
   it.  */
int
dither (MAP *map, int req_w, int req_h, int off_x, int off_y, int req_c, const char *file)
{
  int y;
  int colors;
  COLOR *pmap;
  PALETTE *pal;

  pal = map->palette;
  colors = 0;
  while (pal)
    {
      if (pal->number >= colors)
	colors = pal->number + 1;
      pal = pal->next;
    }

  pmap = alloca (sizeof (COLOR) * colors);
  if (!pmap)
    {
      view_message (0, "alloca palette map");
      exit (1);
    }

  colors = map_colors (pmap, &map->palette, colors, req_c);

  /* For now, we just scale it.  Better check this is enough... */
  if (req_c < colors)
    {
      view_message ("too many colors", "`%s'", file);
      return 1;
    }

  if (set_colors (map->palette))
    return 1;

  y = req_h;
  while (y--)
    {
      int x = req_w;
      COLOR *line = map->image[y * map->height / req_h];

      while (x--)
	{
	  plot_pixel (x + off_x, y + off_y, pmap[line[x * map->width / req_w]]);
	  if (last_sig)
	    return 1;
	}
    }
  return 0;
}
