/*
 * This software is copyrighted as noted below.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is
 * preserved on all copies.
 *
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the author, who may or may not act on them as he desires.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 */
/*
 * change.c - change a given color (and an error) with other.
 *
 * Author:      Raul Rivero
 *              Mathematics Dept.
 *              University of Oviedo
 * Date:        Thu Jan 16 1992
 * Copyright (c) 1992, Raul Rivero
 *
 */

#include <lug.h>
#include <lugfnts.h>

extern int LUGverbose;

changecolor(inbitmap, outbitmap, cR, cG, cB, nR, nG, nB, distance)
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
int cR, cG, cB;
int nR, nG, nB;
int distance;
{
  byte *ir, *ig, *ib;
  byte *or, *og, *ob;
  int totalsize;
  int radix;
  byte *end;
  int curdist;
  double h, s, l;
  double oh, os, ol;

  if ( inbitmap->magic != LUGUSED )
    error( 19 );

  cR = LIMITPIXEL( cR );
  cG = LIMITPIXEL( cG );
  cB = LIMITPIXEL( cB );
  nR = LIMITPIXEL( nR );
  nG = LIMITPIXEL( nG );
  nB = LIMITPIXEL( nB );

  VPRINTF(stderr, "Changing colors\n");
#ifdef DEBUG
  VPRINTF(stderr, "Changing from (%d, %d, %d) to (%d, %d, %d)\n");
  VPRINTF(stderr, "And error of %d\%\n", distance);
#endif

  /*
   * Check if the distance [1..100].
   */
  if ( distance < 0 || distance > 100 )
    error( 9 );

  /* We need an RGB image */
  if ( inbitmap->depth <= 8 )
    error( 7 );

  /* Fill new header */
  outbitmap->magic = LUGUSED;
  outbitmap->xsize = inbitmap->xsize;
  outbitmap->ysize = inbitmap->ysize;
  outbitmap->depth = inbitmap->depth;
  outbitmap->colors = inbitmap->colors;

  /* Allocate memory */
  totalsize = outbitmap->xsize * outbitmap->ysize;
  or = outbitmap->r = (byte *) Malloc( totalsize );
  og = outbitmap->g = (byte *) Malloc( totalsize );
  ob = outbitmap->b = (byte *) Malloc( totalsize );

  /* Set pointers to input image */
  ir = inbitmap->r;
  ig = inbitmap->g;
  ib = inbitmap->b;

  /*
   * Calculate the radix.
   */
  radix = distance / 200.;      /* ( distante / 2 ) / 100 */

  /*
   * Convert the original RGB to HSL.
   */
  RGB_to_HSL( cR, cG, cB, &oh, &os, &ol );

  end = or + totalsize;
  while ( or < end ) {
    /*
     * Convert the current color to HSL and calculate
     * the distance to the given color.
     */
    RGB_to_HSL( *ir, *ig, *ib, &h, &s, &l );
    curdist = ol - l;

    /*
     * Check if we need change this color.
     */
    if ( ABS(curdist) <= radix ) {
      /* We change the current color with ... */
      HSL_to_RGB( h, s, ol, or, og, ob );
      or++, og++, ob++;
      ir++, ig++, ib++;
    }else {
      /* Set the same color */
      *or++ = *ir++;
      *og++ = *ig++;
      *ob++ = *ib++;
    }
  }
}
