/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program 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 1, 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.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/




/*
 *			File: C_dither.c
 *		      Author: Lisa Sobierajski 
 *			Date: 03/07/92
 *		 Description: Dithering Routines Of The Image Viewer 
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

#include <stdio.h>

#include "C_volvis.h"
#include "MOTIF_windefs.h"

C_Byte *C_dither_image_8bit( image )
C_Image		*image;
{
	extern C_WindowDefs	window_defs;
	extern C_World		world;

	C_Byte			*rptr, *gptr, *bptr;
	C_Byte			*image_data, *iptr;
	int			loop;
	C_Byte			*dit_red, *dit_green, *dit_blue;
	C_Byte			*drptr, *dgptr, *dbptr;
	int			approximate_color;
	int			diff_color;
	int			x, y;
	int			error1, error2, error3, error4;
	int			dit_value;

	rptr = image->red;
	gptr = image->green;
	bptr = image->blue;
	dit_red = (C_Byte *) malloc( image->width * image->height );
	dit_green = (C_Byte *) malloc( image->width * image->height );
	dit_blue = (C_Byte *) malloc( image->width * image->height );

	drptr = dit_red;
	dgptr = dit_green;
	dbptr = dit_blue;

	for ( y = 0; y < image->width * image->height; y++ )
	{
		*(drptr++) = 0;
		*(dgptr++) = 0;
		*(dbptr++) = 0;
	}
		
	drptr = dit_red;
	dgptr = dit_green;
	dbptr = dit_blue;

	for (y = 0; y < image->height; y++)
	{
	  for ( x = 0; x < image->width; x++ )
	  {
	    if ( x == 0 || y == 0 || 
	         x == (image->width-1) || y == (image->height-1) )
	    {
		*(drptr++) += *(rptr++);
		*(dgptr++) += *(gptr++);
		*(dbptr++) += *(bptr++);
	    }
	    else 
	    {
	        if ( *(rptr) == world.world_shade.bkgrnd_color.red &&
	             *(gptr) == world.world_shade.bkgrnd_color.green &&
	             *(bptr) == world.world_shade.bkgrnd_color.blue ) 
	        {
		  *(drptr) = *(rptr);
		  *(dgptr) = *(gptr);
		  *(dbptr) = *(bptr);
	        }
	        else
	        {
		  dit_value = *(drptr) + *(rptr);
		  if ( dit_value < 0 ) dit_value = 0;
		  if ( dit_value > 255 ) dit_value = 255;
		  *(drptr) = dit_value;
		  dit_value = *(dgptr) + *(gptr);
		  if ( dit_value < 0 ) dit_value = 0;
		  if ( dit_value > 255 ) dit_value = 255;
		  *(dgptr) = dit_value;
		  dit_value = *(dbptr) + *(bptr);
		  if ( dit_value < 0 ) dit_value = 0;
		  if ( dit_value > 255 ) dit_value = 255;
		  *(dbptr) = dit_value;
	        }

		approximate_color = 
			((int)((float)(*drptr)/63.75))*63.75;
		diff_color = (int)(*drptr) - approximate_color;
		error1 = (int)((0.4375) * (float)diff_color);
		error2 = (int)((0.1875) * (float)diff_color);
		error3 = (int)((0.3125) * (float)diff_color);
		error4 = diff_color - (error1 + error2 + error3);
		dit_value = *(drptr + 1) + error1;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(drptr + 1) = dit_value;
		dit_value = *(drptr - 1 + image->width) + error2;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(drptr - 1 + image->width) = dit_value;
		dit_value = *(drptr + image->width) + error3;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(drptr + image->width) = dit_value;
		dit_value = *(drptr + 1 + image->width) + error4;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(drptr + 1 + image->width) = dit_value;

		approximate_color = 
			((int)((float)(*dgptr)/63.75))*63.75;
		diff_color = (int)(*dgptr) - approximate_color;
		error1 = (int)((0.4375) * (float)diff_color);
		error2 = (int)((0.1875) * (float)diff_color);
		error3 = (int)((0.3125) * (float)diff_color);
		error4 = diff_color - (error1 + error2 + error3);
		dit_value = *(dgptr + 1) + error1;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dgptr + 1) = dit_value;
		dit_value = *(dgptr - 1 + image->width) + error2;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dgptr - 1 + image->width) = dit_value;
		dit_value = *(dgptr + image->width) + error3;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dgptr + image->width) = dit_value;
		dit_value = *(dgptr + 1 + image->width) + error4;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dgptr + 1 + image->width) = dit_value;

		approximate_color = 
			((int)((float)(*dbptr)/63.75))*63.75;
		diff_color = (int)(*dbptr) - approximate_color;
		error1 = (int)((0.4375) * (float)diff_color);
		error2 = (int)((0.1875) * (float)diff_color);
		error3 = (int)((0.3125) * (float)diff_color);
		error4 = diff_color - (error1 + error2 + error3);
		dit_value = *(dbptr + 1) + error1;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dbptr + 1) = dit_value;
		dit_value = *(dbptr - 1 + image->width) + error2;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dbptr - 1 + image->width) = dit_value;
		dit_value = *(dbptr + image->width) + error3;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dbptr + image->width) = dit_value;
		dit_value = *(dbptr + 1 + image->width) + error4;
		if ( dit_value < 0 ) dit_value = 0;
		if ( dit_value > 255 ) dit_value = 255;
		*(dbptr + 1 + image->width) = dit_value;

		drptr++;
		dgptr++;
		dbptr++;
		rptr++;
		gptr++;
		bptr++;
	    }
	  }
	}

	drptr = dit_red;
	dgptr = dit_green;
	dbptr = dit_blue;

	image_data = (C_Byte *) malloc( image->width * image->height );
	iptr = image_data;
	for (loop = 0; loop < image->width * image->height; loop++)
	{
	  *(iptr++) = window_defs.first_color_index + 
		(int)((float)(*(drptr++))/63.75)*25 +
		(int)((float)(*(dgptr++))/63.75)*5 +
		(int)((float)(*(dbptr++))/63.75); 
	}

	free( dit_red );
	free( dit_green );
	free( dit_blue );

	return image_data;

}
