/**
 * $Id:$
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 *
 * The contents of this file may be used under the terms of either the GNU
 * General Public License Version 2 or later (the "GPL", see
 * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or
 * later (the "BL", see http://www.blender.org/BL/ ) which has to be
 * bought from the Blender Foundation to become active, in which case the
 * above mentioned GPL option does not apply.
 *
 * The Original Code is Copyright (C) 2002 by NaN Holding BV.
 * All rights reserved.
 *
 * The Original Code is: all of this file.
 *
 * Contributor(s): none yet.
 *
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 */
/*
 * pixelblending.c
 *
 * Functions to blend pixels with or without alpha, in various formats
 * nzc - June 2000
 *
 * Version: $Id: pixelblending.c,v 1.3 2000/09/11 13:13:00 nzc Exp $
 */
/* global includes */
#include "blender.h"
#include "render.h"
/* local includes */
#include "vanillaRenderPipe_types.h"
/* own includes */
#include "pixelblending_types.h"
#include "pixelblending.h"
/* externals */
/* ------------------------------------------------------------------------- */
/* Debug/behaviour defines                                                   */
/* if defined: alpha blending with floats clips colour, as with shorts       */
/* #define RE_FLOAT_COLOUR_CLIPPING  */
/* if defined: alpha values are clipped                                      */
/* For now, we just keep alpha clipping. We run into thresholding and        */
/* blending difficulties otherwise. Be careful here.                         */
#define RE_ALPHA_CLIPPING
/* One of these three MUST be set.                                           */
/* if defined: do 'expensive' gamma correction, ie. without lookup table.    */
/*  #define RE_PRIMITIVE_GAMMA_CORRECTION  */
/* if defined: lookup-table and interpolation gamma correction.              */
#define RE_INTERPOLATED_GAMMA_CORRECTION
/* if defined: no gamma correction.                                          */
/*  #define RE_NO_GAMMA_CORRECTION  */
/* These indicate the status of the gamma lookup table --------------------- */
static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
static float colour_domain_table[RE_GAMMA_TABLE_SIZE + 1];
static float colour_step;
static float inv_colour_step;
static float valid_gamma;
static float valid_inv_gamma;
static int   gamma_table_initialised = 0;
/* functions --------------------------------------------------------------- */
void addAddSampColF(float *sampvec, float *source, int mask, int osaNr, 
                    uchar addfac)
{
	int a;
	
	for(a=0; a < osaNr; a++) {
		if(mask & (1< RE_FULL_COLOUR_FLOAT) retval--;
		sampvec+= 4;
	}
	return retval;
} /* end of int addToSampColF(float, float, int, int) */
/* ------------------------------------------------------------------------- */
int addToSampCol(ushort *sampcol, ushort *shortcol, int mask, int osaNr)
{
	int a, retval = osaNr;
	
	for(a=0; a < osaNr; a++) {
		if(mask & (1<0xFFF0) retval--;
		sampcol+= 4;
	}
	return retval;
} /* end of int addToSampCol(ushort, uhost, int, int) */
/* ------------------------------------------------------------------------- */
int addtosampcol(ushort *sampcol, ushort *shortcol, int mask)
{
	int a, retval = R.osa;
	
	for(a=0; a < R.osa; a++) {
		if(mask & (1<0xFFF0) retval--;
		sampcol+= 4;
	}
	return retval;
} /* end of int addtosampcol(ushort *sampcol, ushort *shortcol, int mask) */
/* ------------------------------------------------------------------------- */
void addAlphaOverShort(ushort *doel, ushort *bron)   /* vult bron over doel in met alpha van bron */
{
	uint c;
	uint mul;
	if( doel[3]==0 || bron[3]>=0xFFF0) {	/* is getest, scheelt veel */
		*((uint *)doel)= *((uint *)bron);
		*((uint *)(doel+2))= *((uint *)(bron+2));
		return;
	}
	mul= 0xFFFF-bron[3];
	c= ((mul*doel[0])>>16)+bron[0];
	if(c>=0xFFF0) doel[0]=0xFFF0; 
	else doel[0]= c;
	c= ((mul*doel[1])>>16)+bron[1];
	if(c>=0xFFF0) doel[1]=0xFFF0; 
	else doel[1]= c;
	c= ((mul*doel[2])>>16)+bron[2];
	if(c>=0xFFF0) doel[2]=0xFFF0; 
	else doel[2]= c;
	c= ((mul*doel[3])>>16)+bron[3];
	if(c>=0xFFF0) doel[3]=0xFFF0; 
	else doel[3]= c;
} /* end of void addAlphaOverShort(ushort *doel, ushort *bron) */
/* ------------------------------------------------------------------------- */
void addAlphaUnderShort(ushort *doel, ushort *bron)   /* vult bron onder doel in met alpha van doel */
{
	register uint c;
	register uint mul;
	if(doel[3]>=0xFFF0) return;
	if( doel[3]==0 ) {	/* is getest, scheelt veel */
		*((uint *)doel)= *((uint *)bron);
		*((uint *)(doel+2))= *((uint *)(bron+2));
		return;
	}
	mul= 0xFFFF-doel[3];
	c= ((mul*bron[0])>>16)+doel[0];
	if(c>=0xFFF0) doel[0]=0xFFF0; 
	else doel[0]= c;
	c= ((mul*bron[1])>>16)+doel[1];
	if(c>=0xFFF0) doel[1]=0xFFF0; 
	else doel[1]= c;
	c= ((mul*bron[2])>>16)+doel[2];
	if(c>=0xFFF0) doel[2]=0xFFF0;
	else doel[2]= c;
	c= ((mul*bron[3])>>16)+doel[3];
	if(c>=0xFFF0) doel[3]=0xFFF0;
	else doel[3]= c;
} /* end of void addAlphaUnderShort(ushort *doel, ushort *bron) */
  
/* ------------------------------------------------------------------------- */
void addAlphaOverFloat(float *dest, float *source)
{
    /* d = s + (1-alpha_s)d*/
    float c;
    float mul;
    
    /* I may want to disable this clipping */
#ifdef RE_FLOAT_COLOUR_CLIPPING
    if( /*  (-RE_FULL_COLOUR_FLOAT < source[3]) */
/*          && */ (source[3] >  RE_FULL_COLOUR_FLOAT) ) {	/* is getest, scheelt veel */
        dest[0] = source[0];
        dest[1] = source[1];
        dest[2] = source[2];
        dest[3] = source[3];
        return;
    }
#endif
	mul= 1.0 - source[3];
	c= (mul*dest[0]) + source[0];
#ifdef RE_FLOAT_COLOUR_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[0]= c;
   
	c= (mul*dest[1]) + source[1];
#ifdef RE_FLOAT_COLOUR_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[1]= c;
	c= (mul*dest[2]) + source[2];
#ifdef RE_FLOAT_COLOUR_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[2]= c;
	c= (mul*dest[3]) + source[3];
#ifdef RE_ALPHA_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[3]= c;
} /* end of void addAlphaOverFloat(float *doel, float *bron) */
/* ------------------------------------------------------------------------- */
void addAlphaUnderFloat(float *dest, float *source)
{
    float c;
    float mul;
    
    /* I may want to disable this clipping */
#ifdef RE_FLOAT_COLOUR_CLIPPING
    if( dest[3] >= RE_FULL_COLOUR_FLOAT) return;
#endif
    if( (-RE_EMPTY_COLOUR_FLOAT < dest[3])
        && (dest[3] <  RE_EMPTY_COLOUR_FLOAT) ) {	/* is getest, scheelt veel */
        dest[0] = source[0];
        dest[1] = source[1];
        dest[2] = source[2];
        dest[3] = source[3];
        return;
    }
	mul= 1.0 - dest[3];
	c= (mul*source[0]) + dest[0];
#ifdef RE_FLOAT_COLOUR_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[0]= c;
   
	c= (mul*source[1]) + dest[1];
#ifdef RE_FLOAT_COLOUR_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[1]= c;
	c= (mul*source[2]) + dest[2];
#ifdef RE_FLOAT_COLOUR_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[2]= c;
	c= (mul*source[3]) + dest[3];
#ifdef RE_ALPHA_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT; 
	else 
#endif
       dest[3]= c;
} /* end of void addAlphaUnderFloat(float *doel, float *bron) */
/* ------------------------------------------------------------------------- */
void cpShortColV2CharColV(ushort *source, uchar *dest)
{
    dest[0] = source[0]>>8;
    dest[1] = source[1]>>8;
    dest[2] = source[2]>>8;
    dest[3] = source[3]>>8;
} /* end of void cpShortColV2CharColV(ushort *source, uchar *dest) */
/* ------------------------------------------------------------------------- */
void cpCharColV2ShortColV(uchar *source, ushort *dest)
{
    dest[0] = source[0]<<8;
    dest[1] = source[1]<<8;
    dest[2] = source[2]<<8;
    dest[3] = source[3]<<8;
} /* end of void cpShortColV2CharColV(uchar *source, ushort *dest) */
/* ------------------------------------------------------------------------- */
void cpIntColV2CharColV(uint *source, uchar *dest)
{
    dest[0] = source[0]>>24;
    dest[1] = source[1]>>24;
    dest[2] = source[2]>>24;
    dest[3] = source[3]>>24;
} /* end of void cpIntColV2CharColV(uint *source, uchar *dest) */
/* ------------------------------------------------------------------------- */
void cpCharColV2FloatColV(uchar *source, float *dest)
{
    dest[0] = source[0]/255.0;  
    dest[1] = source[1]/255.0;  
    dest[2] = source[2]/255.0;
    dest[3] = source[3]/255.0;
} /* end of void cpCharColV2FloatColV(char *source, float *dest) */
/* ------------------------------------------------------------------------- */
void cpShortColV2FloatColV(ushort *source, float *dest)
{
    dest[0] = source[0]/65535.0;  
    dest[1] = source[1]/65535.0;  
    dest[2] = source[2]/65535.0;
    dest[3] = source[3]/65535.0;
} /* end of void cpShortColV2FloatColV(char *source, float *dest) */
/* ------------------------------------------------------------------------- */
void cpFloatColV2CharColV(float* source, uchar *dest)
{
  /* can't this be done more efficient? hope the conversions are correct... */
  if (source[0] < 0.0)      dest[0] = 0;
  else if (source[0] > 1.0) dest[0] = 255;
  else dest[0] = (uchar) (source[0] * 255.0);
  if (source[1] < 0.0)      dest[1] = 0;
  else if (source[1] > 1.0) dest[1] = 255;
  else dest[1] = (uchar) (source[1] * 255.0);
  if (source[2] < 0.0)      dest[2] = 0;
  else if (source[2] > 1.0) dest[2] = 255;
  else dest[2] = (uchar) (source[2] * 255.0);
  if (source[3] < 0.0)      dest[3] = 0;
  else if (source[3] > 1.0) dest[3] = 255;
  else dest[3] = (uchar) (source[3] * 255.0);
} /* end of void cpFloatColV2CharColV(float* source, uchar *dest) */
/* ------------------------------------------------------------------------- */
void cpShortColV(ushort *source, ushort *dest)
{
    dest[0] = source[0];
    dest[1] = source[1];
    dest[2] = source[2];
    dest[3] = source[3];
} /* end of void cpShortColV(ushort *source, ushort *dest) */
/* ------------------------------------------------------------------------- */
void cpFloatColV(float *source, float *dest)
{
    dest[0] = source[0];
    dest[1] = source[1];
    dest[2] = source[2];
    dest[3] = source[3];
} /* end of void cpFloatColV(float *source, float *dest) */
/* ------------------------------------------------------------------------- */
void cpCharColV(uchar *source, uchar *dest)
{
    dest[0] = source[0];
    dest[1] = source[1];
    dest[2] = source[2];
    dest[3] = source[3];
} /* end of void cpCharColV(uchar *source, uchar *dest) */
/* ------------------------------------------------------------------------- */
void addalphaAddfacFloat(float *dest, float *source, uchar addfac)
  /* doel= bron over doel  */
{
    float m; /* weiging factor of destination */
    float c; /* intermediate colour           */
    /* 1. copy source straight away if dest has zero alpha */
	/* 2. copy dest straight away if dest has full alpha   */
	/* I am not sure whether (2) is correct. It seems to   */
	/* me that this should not happen if float colours     */
	/* aren't clipped at 1.0 .                             */
	/* I'll keep the code, but disabled....                */
    if ( (dest[3] < RE_EMPTY_COLOUR_FLOAT) 
		/*   || source[3] > RE_FULL_COLOUR_FLOAT */ ) {
        dest[0] = source[0];
        dest[1] = source[1];
        dest[2] = source[2];
        dest[3] = source[3];
        return;
    }
    /* Addfac is a number between 0 and 1: rescale */
    /* final target is to diminish the influence of dest when addfac rises */
    m = 1.0 - ( source[3] * ((255.0 - addfac) / 255.0));
    /* blend colours*/
    c= (m * dest[0]) + source[0];
#ifdef RE_FLOAT_COLOUR_CLIPPING
    if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_FULL_COLOUR_FLOAT; 
    else 
#endif
        dest[0]= c;
   
    c= (m * dest[1]) + source[1];
#ifdef RE_FLOAT_COLOUR_CLIPPING
    if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_FULL_COLOUR_FLOAT; 
    else 
#endif
        dest[1]= c;
    
    c= (m * dest[2]) + source[2];
#ifdef RE_FLOAT_COLOUR_CLIPPING
    if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_FULL_COLOUR_FLOAT; 
    else 
#endif
        dest[2]= c;
	c= dest[3] + source[3];
#ifdef RE_ALPHA_CLIPPING
	if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_FULL_COLOUR_FLOAT; 
	else 
#endif
       dest[3]= c;
} /* end of void addalphaAddfacFloat(ushort *doel, ushort *bron, uchar addfac_help) */
/* ------------------------------------------------------------------------- */
void addalphaAddfacShort(ushort *doel, ushort *bron, uchar addfac)
  /* doel= bron over doel  */
{
    float m; /* weiging factor of destination */
    float c; /* intermediate colour           */
    /* 1. copy bron straight away if doel has zero alpha */
    if( doel[3] == 0) {
        *((uint *)doel)     = *((uint *)bron);
        *((uint *)(doel+2)) = *((uint *)(bron+2));
        return;
    }
    
    /* Addfac is a number between 0 and 1: rescale */
    /* final target is to diminish the influence of dest when addfac rises */
    m = 1.0 - ( bron[3] * ((255.0 - addfac) / 255.0));
    /* blend colours*/
    c = (m * doel[0]) + bron[0];
    if( c > 65535.0 ) doel[0]=65535; 
    else doel[0] = ffloor(c);
    c = (m * doel[1]) + bron[1];
    if( c > 65535.0 ) doel[1]=65535; 
    else doel[1] = ffloor(c);
    c = (m * doel[2]) + bron[2];
    if( c > 65535.0 ) doel[2]=65535; 
    else doel[2] = ffloor(c);
    c = doel[3] + bron[3];
    if(c > 65535.0) doel[3] = 65535; 
    else doel[3]=  ffloor(c);
} /* end of void addalphaAddfacShort(ushort *doel, ushort *bron, uchar addfac_help) */
/* ------------------------------------------------------------------------- */
void addHaloToHaloShort(ushort *d, ushort *s)
{
    /*  float m; */ /* weiging factor of destination */
    float c[4]; /* intermediate colour           */
    float rescale = 1.0;
    /* 1. copy  straight away if  has zero alpha */
    if( d[3] == 0) {
        *((uint *) d)      = *((uint *) s);
        *((uint *)(d + 2)) = *((uint *)(s + 2));
        return;
    }
    /* 2. halo blending  */
    /* no blending, just add */
    c[0] = s[0] + d[0];
    c[1] = s[1] + d[1];
    c[2] = s[2] + d[2];
    c[3] = s[3] + d[3];
    /* One thing that may happen is that this pixel is over-saturated with light - */
    /* i.e. too much light comes out, and the pixel is clipped. Currently, this    */
    /* leads to artifacts such as overproportional undersampling of background     */
    /* colours.                                                                    */
    /* Compensating for over-saturation:                                           */
    /* - increase alpha                                                            */
    /* - increase alpha and rescale colours                                        */
    /* let's try alpha increase and clipping */
    /* calculate how much rescaling we need */
    if( c[0] > 65535.0 ) { 
      rescale *= c[0] /65535.0;
      d[0] = 65535; 
    } else d[0] = ffloor(c[0]);
    if( c[1] > 65535.0 ) { 
      rescale *= c[1] /65535.0;
      d[1] = 65535; 
    } else d[1] = ffloor(c[1]);
    if( c[2] > 65535.0 ) { 
      rescale *= c[2] /65535.0;
      d[2] = 65535; 
    } else d[2] = ffloor(c[2]);
    /* a bit too hefty I think */
    c[3] *= rescale;
    if( c[3] > 65535.0 ) d[3] = 65535; else d[3]=  ffloor(c[3]);
} /* end of void addHaloToHaloShort(ushort *dest, ushort *source, char addfac) */
/* ------------------------------------------------------------------------- */
void sampleShortColV2ShortColV(ushort *sample, ushort *dest, int osaNr)
{
    uint intcol[4] = {0};
    ushort *scol = sample; 
    int a = 0;
    
    for(a=0; a < osaNr; a++, scol+=4) {
        intcol[0]+= scol[0]; intcol[1]+= scol[1];
        intcol[2]+= scol[2]; intcol[3]+= scol[3];
    }
    
    /* Now normalise the integrated colour. It is guaranteed */
    /* to be correctly bounded.                              */
    dest[0]= intcol[0]/osaNr;
    dest[1]= intcol[1]/osaNr;
    dest[2]= intcol[2]/osaNr;
    dest[3]= intcol[3]/osaNr;
    
} /* end of void sampleShortColVToShortColV(ushort *sample, ushort *dest) */
/* ------------------------------------------------------------------------- */
void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr)
{
    float intcol[4] = {0};
    float *scol = sample; 
    int   a = 0;
#ifdef RE_PRIMITIVE_GAMMA_CORRECTION
	/* Needs to become something with lookup tables.*/
	/* Go to intensities, and integrate those. Don't touch alpha  */
	float invgamma = 1.0 / RE_DEFAULT_GAMMA;
    for(a=0; a < osaNr; a++, scol+=4) {
		intcol[0] += powf(scol[0], RE_DEFAULT_GAMMA);
		intcol[1] += powf(scol[1], RE_DEFAULT_GAMMA);
		intcol[2] += powf(scol[2], RE_DEFAULT_GAMMA);
		intcol[3] += scol[3];
    }
	/* renormalise */
	intcol[0] /= osaNr;
	intcol[1] /= osaNr;
	intcol[2] /= osaNr;
	intcol[3] /= osaNr;
	/* back to pixel values */
	dest[0] = powf(intcol[0], invgamma);
	dest[1] = powf(intcol[1], invgamma);
	dest[2] = powf(intcol[2], invgamma);
	dest[3] = intcol[3];
	return;		
#endif
#ifdef RE_INTERPOLATED_GAMMA_CORRECTION
	/* use a LUT and interpolation to do the gamma correction */
	for(a=0; a < osaNr; a++, scol+=4) {
  		intcol[0] += gammaCorrect(scol[0]); 
  		intcol[1] += gammaCorrect(scol[1]); 
  		intcol[2] += gammaCorrect(scol[2]); 
		intcol[3] += scol[3];
    }
	/* renormalise */
	intcol[0] /= osaNr;
	intcol[1] /= osaNr;
	intcol[2] /= osaNr;
	intcol[3] /= osaNr;
	/* back to pixel values */
	dest[0] = invGammaCorrect(intcol[0]);
	dest[1] = invGammaCorrect(intcol[1]);
	dest[2] = invGammaCorrect(intcol[2]);
	dest[3] = intcol[3];
	return;		
#endif
#ifdef RE_NO_GAMMA_CORRECTION
	/* Each colour should be weighted by alpha? We need gamma correction     */
	/* badly */
    for(a=0; a < osaNr; a++, scol+=4) {
		intcol[0] += scol[0]; intcol[1] += scol[1];
		intcol[2] += scol[2]; intcol[3] += scol[3];
    }
    
    dest[0]= intcol[0]/osaNr;
    dest[1]= intcol[1]/osaNr;
    dest[2]= intcol[2]/osaNr;
    dest[3]= intcol[3]/osaNr;
#endif
	
} /* end of void sampleFloatColVToFloatColV(ushort *sample, ushort *dest) */
/* ------------------------------------------------------------------------- */
float gammaCorrect(float c)
{
	int i;
	float res = 0.0;
	
	i = ffloor(c * inv_colour_step);
	/* Clip to range [0,1]: outside, just do the complete calculation.       */
	/* We may have some performance problems here. Stretching up the LUT     */
	/* may help solve that, by exchanging LUT size for the interpolation.    */
	if (i < 0) res = powf(c, valid_gamma);
	else if (i >= RE_GAMMA_TABLE_SIZE ) res = powf(c, valid_gamma);
	else res = gamma_range_table[i] + 
  			 ( (c - colour_domain_table[i]) * gamfactor_table[i]); 
	
	
	return res;
} /* end of float gammaCorrect(float col) */
/* ------------------------------------------------------------------------- */
float invGammaCorrect(float col)
{
	int i;
	float res = 0.0;
	i = ffloor(col*inv_colour_step);
	if (i < 0) res = powf(col, valid_inv_gamma);
	else if (i >= RE_GAMMA_TABLE_SIZE) res = powf(col, valid_inv_gamma);
	else res = inv_gamma_range_table[i] + 
  			 ( (col - colour_domain_table[i]) * inv_gamfactor_table[i]);
			   
	return res;
} /* end of float invGammaCorrect(float col) */
/* ------------------------------------------------------------------------- */
void makeGammaTables(float gamma)
{
	/* we need two tables: one forward, one backward */
	int i;
	valid_gamma        = gamma;
	valid_inv_gamma    = 1.0 / gamma;
	colour_step        = 1.0 / RE_GAMMA_TABLE_SIZE;
	inv_colour_step    = (float) RE_GAMMA_TABLE_SIZE; 
	/* We could squeeze out the two range tables to gain some memory.        */	
	for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
		colour_domain_table[i]   = i * colour_step;
		gamma_range_table[i]     = powf(colour_domain_table[i],
										valid_gamma);
		inv_gamma_range_table[i] = powf(colour_domain_table[i],
										valid_inv_gamma);
	}
	/* The end of the table should match 1.0 carefully. In order to avoid    */
	/* rounding errors, we just set this explicitly. The last segment may    */
	/* have a different lenght than the other segments, but our              */
	/* interpolation is insensitive to that.                                 */
	colour_domain_table[RE_GAMMA_TABLE_SIZE]   = 1.0;
	gamma_range_table[RE_GAMMA_TABLE_SIZE]     = 1.0;
	inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
	/* To speed up calculations, we make these calc factor tables. They are  */
	/* multiplication factors used in scaling the interpolation.             */
	for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
		gamfactor_table[i] = inv_colour_step
			* (gamma_range_table[i + 1] - gamma_range_table[i]) ;
		inv_gamfactor_table[i] = inv_colour_step
			* (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
	}
	gamma_table_initialised = 1;
} /* end of void makeGammaTables(float gamma) */
/* ------------------------------------------------------------------------- */
int gammaTableIsInitialised(void)
{
	return gamma_table_initialised;
}
/* ------------------------------------------------------------------------- */
/* eof pixelblending.c */