/*
 * 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.
 */
/*
 * histoequ.c - perform an historgram equalization.
 *
 * Author:      Raul Rivero
 *              Mathematics Dept.
 *              University of Oviedo
 * Date:        Sun Mar 08 1992
 * Copyright (c) 1992, Raul Rivero
 *
 */

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

/********************************************************************
 *
 * TAG( histogram_equalization )
 *      Perform a histogram equalization on an input image.
 *
 * Inputs:
 *      inbitmap:       the original image
 *
 * Outputs:
 *      outbitmap:      the resulting image 
 *
 * Assumptions:
 *      Only true color images. If you need equalize a mapped image, 
 *      first convert it to 24 bits, equalize and then restore to 
 *      the orignal depth.
 *
 *      This restriction could be thinked as a bug, but so we can handle
 *      a wider range of images.
 *
 * Algorithm:
 *      [None]
 *
 */      

histogram_equalization(inbitmap, outbitmap)
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
{
  register int i;
  int total_size;
  byte *ir, *ig, *ib;
  byte *or, *og, *ob;
  double h, s, l;
  byte *end;
  double pr[256];
  int times[256];

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

  /* Initialize 'times' */
  bzero( times, 256 * sizeof(int) );

  /* We need a true color image */
  if ( inbitmap->depth < 24 )
    error( 7 );

  /* Fill new header */
  outbitmap->magic = LUGUSED;
  outbitmap->xsize = inbitmap->xsize;
  outbitmap->ysize = inbitmap->ysize;
  outbitmap->depth = 24;
  outbitmap->colors = ( 1 << outbitmap->depth );
  total_size  = outbitmap->xsize * outbitmap->ysize;

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

  /* Pointers to in image */
  ir = inbitmap->r;
  ig = inbitmap->g;
  ib = inbitmap->b;
  end = ir + total_size;

  while ( ir < end ) {
    RGB_to_HSL( *ir, *ig, *ib, &h, &s, &l );
    times[(int)(255. * l)]++;
    ir++, ig++, ib++;
  }

  for ( i = 0; i < 256; i++ ) {
    pr[i] = ((double) times[i]) / (double) total_size;
    if ( i )
      pr[i] += pr[i-1];
  }

  /* Pointers to in image */
  ir = inbitmap->r;
  ig = inbitmap->g;
  ib = inbitmap->b;

  while ( ir < end ) {
    RGB_to_HSL( *ir, *ig, *ib, &h, &s, &l );
    l = pr[(int)((double)255.*l)];
    HSL_to_RGB( h, s, l, or, og, ob );
    ir++, ig++, ib++;
    or++, og++, ob++;
  }
}
