/////////////////////////////////////////////////////////////////////////////////////////////////////
//																																	//
//	Coded by www.decotechpro.com, all rights reserved.  Created: 1999-01-01©  Modified: 2016-03-21©	//
//																																	//
// JCH_Pixel.h : Header of miscellaneous 32 bits pixel routines.												//
//																																	//
/////////////////////////////////////////////////////////////////////////////////////////////////////

//#include "TT_Pixel.h"
#pragma once

#include <afxwin.h>

/////////////////////////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////////////////////////

#define	JCH_PIXEL_CHANNEL_MIN_VAL			0
#define	JCH_PIXEL_CHANNEL_MAX_VAL			255
#define	JCH_PIXEL_CHANNEL_HALFMAX_VAL		(JCH_PIXEL_CHANNEL_MAX_VAL / 2)

#define	JCH_PIXEL_MIX_AMOUNT_MIN_VAL		JCH_PIXEL_CHANNEL_MIN_VAL
#define	JCH_PIXEL_MIX_AMOUNT_MAX_VAL		JCH_PIXEL_CHANNEL_MAX_VAL
#define	JCH_PIXEL_MIX_AMOUNT_HALFMAX_VAL	(JCH_PIXEL_MIX_AMOUNT_MAX_VAL / 2)
#define	JCH_PIXEL_MIX_GRADIENT_STEP_MIN	2
#define	JCH_PIXEL_MIX_GRADIENT_STEP_MAX	(JCH_PIXEL_CHANNEL_MAX_VAL + 1)

/////////////////////////////////////////////////////////////////////////////////////////////////////



/////////////////////////////////////////////////////////////////////////////////////////////////////

typedef unsigned int JCH_Pixel;		// Alpha(24,31) - Red(16,23) - Green(8,15) - Blue(0,7)

enum	// Used to directly access memory
{
	JCH_PixelBluePos	= 0,
	JCH_PixelGreenPos = 1,
	JCH_PixelRedPos	= 2,
	JCH_PixelAlphaPos = 3,
};		

//------------------------------------------------

inline unsigned int JCH_PixelGetRed(	const JCH_Pixel cPixel ) { return( ((unsigned char *)&cPixel)[JCH_PixelRedPos  ] ); }
inline unsigned int JCH_PixelGetGreen( const JCH_Pixel cPixel ) { return( ((unsigned char *)&cPixel)[JCH_PixelGreenPos] ); }
inline unsigned int JCH_PixelGetBlue(  const JCH_Pixel cPixel ) { return( ((unsigned char *)&cPixel)[JCH_PixelBluePos ] ); }
inline unsigned int JCH_PixelGetAlpha( const JCH_Pixel cPixel ) { return( ((unsigned char *)&cPixel)[JCH_PixelAlphaPos] ); }

//------------------------------------------------

inline JCH_Pixel JCH_PixelFromRGBA( const unsigned int cunRed, const unsigned int cunGreen, 
												const unsigned int cunBlue, const unsigned int cunAlpha = JCH_PIXEL_CHANNEL_MAX_VAL )
{
	return( ((cunAlpha << 24) | (cunRed << 16) | (cunGreen << 8) | cunBlue) );
}

inline JCH_Pixel JCH_PixelFromColorRef( const COLORREF cColor )
{
	return( (0xFF000000 | ((cColor & 0xFF) << 16) | (cColor & 0xFF00) | ((unsigned char *)&cColor)[2]) );
}

inline COLORREF JCH_PixelToColorRef( const JCH_Pixel cPixel )
{
	return( (((cPixel & 0xFF) << 16) | (cPixel & 0xFF00) | ((unsigned char *)&cPixel)[JCH_PixelRedPos]) );
}

//------------------------------------------------

//	JCH_PIXELMIX_AMOUNT_MIN			 <= 'cunPixel2Amount'		<= JCH_PIXEL_MIX_AMOUNT_MAX_VAL.
//	JCH_PIXELMIX_GRADIENT_STEP_MIN <= 'cunTotalGradientStep' <= JCH_PIXEL_MIX_GRADIENT_STEP_MAX.
inline JCH_Pixel JCH_PixelMixRGBA( const JCH_Pixel cPixel1, const JCH_Pixel cPixel2, const unsigned int cunPixel2Amount,
											  const unsigned int cunTotalGradientStep = JCH_PIXEL_MIX_GRADIENT_STEP_MAX )
{
	unsigned int	unNewPixel2Amount, unPixel1Amount, unCurGradientStep;
	int				nR, nG, nB, nA;
	
	if ( cunTotalGradientStep != JCH_PIXEL_MIX_GRADIENT_STEP_MAX )
	{
		unCurGradientStep = (cunTotalGradientStep * cunPixel2Amount / (JCH_PIXEL_MIX_AMOUNT_MAX_VAL + 1));			
		unNewPixel2Amount = (((unCurGradientStep * JCH_PIXEL_MIX_AMOUNT_MAX_VAL) + ((cunTotalGradientStep - 1) / 2)) / (cunTotalGradientStep - 1));
	}
	else unNewPixel2Amount = cunPixel2Amount;
	
	unPixel1Amount = (JCH_PIXEL_MIX_AMOUNT_MAX_VAL - unNewPixel2Amount);
	
	nR = (((JCH_PixelGetRed(   cPixel1 ) * unPixel1Amount   ) +
			 (JCH_PixelGetRed(   cPixel2 ) * unNewPixel2Amount) + JCH_PIXEL_MIX_AMOUNT_HALFMAX_VAL) / JCH_PIXEL_MIX_AMOUNT_MAX_VAL);
	nG = (((JCH_PixelGetGreen( cPixel1 ) * unPixel1Amount   ) + 
			 (JCH_PixelGetGreen( cPixel2 ) * unNewPixel2Amount) + JCH_PIXEL_MIX_AMOUNT_HALFMAX_VAL) / JCH_PIXEL_MIX_AMOUNT_MAX_VAL);
	nB = (((JCH_PixelGetBlue(  cPixel1 ) * unPixel1Amount   ) + 
			 (JCH_PixelGetBlue(  cPixel2 ) * unNewPixel2Amount) + JCH_PIXEL_MIX_AMOUNT_HALFMAX_VAL) / JCH_PIXEL_MIX_AMOUNT_MAX_VAL);
	nA = (((JCH_PixelGetAlpha( cPixel1 ) * unPixel1Amount   ) + 
			 (JCH_PixelGetAlpha( cPixel2 ) * unNewPixel2Amount) + JCH_PIXEL_MIX_AMOUNT_HALFMAX_VAL) / JCH_PIXEL_MIX_AMOUNT_MAX_VAL);

	return( JCH_PixelFromRGBA( nR, nG, nB, nA ) );
}		 

/////////////////////////////////////////////////////////////////////////////////////////////////////
